2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2021-12-05 21:05:27 +05:30
|
|
|
* SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh
|
|
|
|
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
|
|
|
|
* SPDX-FileCopyrightText: 2001 - 2006, Tomasz Kłoczko
|
|
|
|
* SPDX-FileCopyrightText: 2007 - 2011, Nicolas François
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
2021-12-05 21:05:27 +05:30
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-11-11 05:16:11 +05:30
|
|
|
#ident "$Id$"
|
2007-10-07 17:17:01 +05:30
|
|
|
|
|
|
|
#include <errno.h>
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <fcntl.h>
|
2007-10-07 17:17:01 +05:30
|
|
|
#include <getopt.h>
|
|
|
|
#include <pwd.h>
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <signal.h>
|
2007-10-07 17:17:01 +05:30
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
2023-02-05 03:11:18 +05:30
|
|
|
|
|
|
|
#include "alloc.h"
|
2007-10-07 17:17:01 +05:30
|
|
|
#include "defines.h"
|
|
|
|
#include "getdef.h"
|
|
|
|
#include "nscd.h"
|
Flush sssd caches in addition to nscd caches
Some distributions, notably Fedora, have the following order of nsswitch
modules by default:
passwd: sss files
group: sss files
The advantage of serving local users through SSSD is that the nss_sss
module has a fast mmapped-cache that speeds up NSS lookups compared to
accessing the disk an opening the files on each NSS request.
Traditionally, this has been done with the help of nscd, but using nscd
in parallel with sssd is cumbersome, as both SSSD and nscd use their own
independent caching, so using nscd in setups where sssd is also serving
users from some remote domain (LDAP, AD, ...) can result in a bit of
unpredictability.
More details about why Fedora chose to use sss before files can be found
on e.g.:
https://fedoraproject.org//wiki/Changes/SSSDCacheForLocalUsers
or:
https://docs.pagure.org/SSSD.sssd/design_pages/files_provider.html
Now, even though sssd watches the passwd and group files with the help
of inotify, there can still be a small window where someone requests a
user or a group, finds that it doesn't exist, adds the entry and checks
again. Without some support in shadow-utils that would explicitly drop
the sssd caches, the inotify watch can fire a little late, so a
combination of commands like this:
getent passwd user || useradd user; getent passwd user
can result in the second getent passwd not finding the newly added user
as the racy behaviour might still return the cached negative hit from
the first getent passwd.
This patch more or less copies the already existing support that
shadow-utils had for dropping nscd caches, except using the "sss_cache"
tool that sssd ships.
2018-09-12 17:52:11 +05:30
|
|
|
#include "sssd.h"
|
2007-10-07 17:17:01 +05:30
|
|
|
#include "prototypes.h"
|
|
|
|
#include "pwauth.h"
|
|
|
|
#include "pwio.h"
|
|
|
|
#include "shadowio.h"
|
2021-11-29 05:07:53 +05:30
|
|
|
#include "shadowlog.h"
|
* src/newgrp.c, src/chfn.c, src/groupmems.c, src/usermod.c,
src/userdel.c, src/chpasswd.c, src/grpck.c, src/gpasswd.c,
src/groupdel.c, src/chgpasswd.c, src/vipw.c, src/useradd.c,
src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/faillog.c,
src/sulogin.c, src/chsh.c, src/pwconv.c: Added splint annotations.
* src/userdel.c, src/pwconv.c, src/lastlog.c, src/grpck.c,
src/vipw.c, src/groupmod.c, src/passwd.c, src/pwck.c, src/login.c,
src/sulogin.c, src/usermod.c: Use return instead of exit at the
end of main().
* src/gpasswd.c, src/passwd.c, src/faillog.c: Use the exitcodes.h
exit codes.
* src/chpasswd.c: Added missing ||.
* src/nologin.c: Do not include exitcodes.h.
* src/nologin.c: Added brackets.
* src/nologin.c: Avoid assignments in comparisons.
2009-05-01 03:09:38 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* exit status values
|
|
|
|
*/
|
* src/newgrp.c, src/chfn.c, src/groupmems.c, src/usermod.c,
src/userdel.c, src/chpasswd.c, src/grpck.c, src/gpasswd.c,
src/groupdel.c, src/chgpasswd.c, src/vipw.c, src/useradd.c,
src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/faillog.c,
src/sulogin.c, src/chsh.c, src/pwconv.c: Added splint annotations.
* src/userdel.c, src/pwconv.c, src/lastlog.c, src/grpck.c,
src/vipw.c, src/groupmod.c, src/passwd.c, src/pwck.c, src/login.c,
src/sulogin.c, src/usermod.c: Use return instead of exit at the
end of main().
* src/gpasswd.c, src/passwd.c, src/faillog.c: Use the exitcodes.h
exit codes.
* src/chpasswd.c: Added missing ||.
* src/nologin.c: Do not include exitcodes.h.
* src/nologin.c: Added brackets.
* src/nologin.c: Avoid assignments in comparisons.
2009-05-01 03:09:38 +05:30
|
|
|
/*@-exitarg@*/
|
2007-10-07 17:14:02 +05:30
|
|
|
#define E_SUCCESS 0 /* success */
|
|
|
|
#define E_NOPERM 1 /* permission denied */
|
|
|
|
#define E_USAGE 2 /* invalid combination of options */
|
|
|
|
#define E_FAILURE 3 /* unexpected failure, nothing done */
|
|
|
|
#define E_MISSING 4 /* unexpected failure, passwd file missing */
|
|
|
|
#define E_PWDBUSY 5 /* passwd file busy, try again later */
|
|
|
|
#define E_BAD_ARG 6 /* invalid argument to option */
|
|
|
|
/*
|
|
|
|
* Global variables
|
|
|
|
*/
|
* src/newgrp.c, src/userdel.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/pwconv.c, src/chpasswd.c, src/logoutd.c,
src/chfn.c, src/groupmems.c, src/usermod.c, src/pwunconv.c,
src/expiry.c, src/groupdel.c, src/chgpasswd.c, src/useradd.c,
src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c, src/chage.c,
src/groupadd.c, src/login.c, src/grpconv.c, src/groups.c,
src/grpunconv.c, src/chsh.c: Prog changed to a constant string.
2010-08-23 01:06:09 +05:30
|
|
|
const char *Prog; /* Program name */
|
* src/newgrp.c, src/userdel.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/pwconv.c, src/chpasswd.c, src/logoutd.c,
src/chfn.c, src/groupmems.c, src/usermod.c, src/pwunconv.c,
src/expiry.c, src/groupdel.c, src/chgpasswd.c, src/useradd.c,
src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/grpconv.c,
src/groups.c, src/grpunconv.c, src/chsh.c: Prog is now global (not
static to the file) so that it can be used by the helper functions
of libmisc.
* lib/prototypes.h: Added extern char *Prog.
* libmisc/find_new_gid.c, libmisc/find_new_uid.c: Indicate the
program name with the warning.
2008-09-06 18:21:53 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
static char *name; /* The name of user whose password is being changed */
|
|
|
|
static char *myname; /* The current user's name */
|
2008-06-10 23:20:21 +05:30
|
|
|
static bool amroot; /* The caller's real UID was 0 */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
aflg = false, /* -a - show status for all users */
|
|
|
|
dflg = false, /* -d - delete password */
|
|
|
|
eflg = false, /* -e - force password change */
|
|
|
|
iflg = false, /* -i - set inactive days */
|
|
|
|
kflg = false, /* -k - change only if expired */
|
2008-08-22 07:46:21 +05:30
|
|
|
lflg = false, /* -l - lock the user's password */
|
2008-06-10 23:20:21 +05:30
|
|
|
nflg = false, /* -n - set minimum days */
|
|
|
|
qflg = false, /* -q - quiet mode */
|
|
|
|
Sflg = false, /* -S - show password status */
|
2008-08-22 07:46:21 +05:30
|
|
|
uflg = false, /* -u - unlock the user's password */
|
2008-06-10 23:20:21 +05:30
|
|
|
wflg = false, /* -w - set warning days */
|
|
|
|
xflg = false; /* -x - set maximum days */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* set to 1 if there are any flags which require root privileges,
|
|
|
|
* and require username to be specified
|
|
|
|
*/
|
2008-06-10 23:20:21 +05:30
|
|
|
static bool anyflag = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
static long age_min = 0; /* Minimum days before change */
|
|
|
|
static long age_max = 0; /* Maximum days until change */
|
|
|
|
static long warn = 0; /* Warning days before change */
|
2007-10-07 17:14:02 +05:30
|
|
|
static long inact = 0; /* Days without change before locked */
|
|
|
|
|
2009-04-06 03:34:31 +05:30
|
|
|
#ifndef USE_PAM
|
2008-06-10 23:20:21 +05:30
|
|
|
static bool do_update_age = false;
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* ! USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-08-22 07:54:29 +05:30
|
|
|
static bool pw_locked = false;
|
|
|
|
static bool spw_locked = false;
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifndef USE_PAM
|
2007-11-20 17:48:36 +05:30
|
|
|
/*
|
|
|
|
* Size of the biggest passwd:
|
|
|
|
* $6$ 3
|
|
|
|
* rounds= 7
|
|
|
|
* 999999999 9
|
|
|
|
* $ 1
|
|
|
|
* salt 16
|
|
|
|
* $ 1
|
|
|
|
* SHA512 123
|
|
|
|
* nul 1
|
|
|
|
*
|
|
|
|
* total 161
|
|
|
|
*/
|
|
|
|
static char crypt_passwd[256];
|
2008-06-10 23:20:21 +05:30
|
|
|
static bool do_update_pwd = false;
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* !USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* External identifiers
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* local function prototypes */
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN static void usage (int);
|
2007-10-07 17:14:59 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifndef USE_PAM
|
2010-08-22 18:19:07 +05:30
|
|
|
static bool reuse (const char *, const struct passwd *);
|
2007-10-07 17:14:59 +05:30
|
|
|
static int new_password (const struct passwd *);
|
|
|
|
|
|
|
|
static void check_password (const struct passwd *, const struct spwd *);
|
|
|
|
#endif /* !USE_PAM */
|
2010-08-22 18:19:07 +05:30
|
|
|
static /*@observer@*/const char *pw_status (const char *);
|
2007-10-07 17:14:59 +05:30
|
|
|
static void print_status (const struct passwd *);
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN static void fail_exit (int);
|
|
|
|
NORETURN static void oom (void);
|
2007-10-07 17:14:59 +05:30
|
|
|
static char *update_crypt_pw (char *);
|
|
|
|
static void update_noshadow (void);
|
|
|
|
|
|
|
|
static void update_shadow (void);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* usage - print command usage and exit
|
|
|
|
*/
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN
|
|
|
|
static void
|
|
|
|
usage (int status)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2011-11-07 00:08:16 +05:30
|
|
|
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
|
|
|
|
(void) fprintf (usageout,
|
|
|
|
_("Usage: %s [options] [LOGIN]\n"
|
|
|
|
"\n"
|
|
|
|
"Options:\n"),
|
|
|
|
Prog);
|
|
|
|
(void) fputs (_(" -a, --all report password status on all accounts\n"), usageout);
|
|
|
|
(void) fputs (_(" -d, --delete delete the password for the named account\n"), usageout);
|
|
|
|
(void) fputs (_(" -e, --expire force expire the password for the named account\n"), usageout);
|
|
|
|
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
|
|
|
(void) fputs (_(" -k, --keep-tokens change password only if expired\n"), usageout);
|
|
|
|
(void) fputs (_(" -i, --inactive INACTIVE set password inactive after expiration\n"
|
|
|
|
" to INACTIVE\n"), usageout);
|
|
|
|
(void) fputs (_(" -l, --lock lock the password of the named account\n"), usageout);
|
|
|
|
(void) fputs (_(" -n, --mindays MIN_DAYS set minimum number of days before password\n"
|
|
|
|
" change to MIN_DAYS\n"), usageout);
|
|
|
|
(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 (_(" -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);
|
|
|
|
(void) fputs (_(" -x, --maxdays MAX_DAYS set maximum number of days before password\n"
|
|
|
|
" change to MAX_DAYS\n"), usageout);
|
|
|
|
(void) fputs ("\n", usageout);
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (status);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef USE_PAM
|
2010-08-22 18:19:07 +05:30
|
|
|
static bool reuse (const char *pass, const struct passwd *pw)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
#ifdef HAVE_LIBCRACK_HIST
|
|
|
|
const char *reason;
|
2007-10-07 17:14:59 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef HAVE_LIBCRACK_PW
|
2007-10-07 17:14:59 +05:30
|
|
|
const char *FascistHistoryPw (const char *, const struct passwd *);
|
|
|
|
|
|
|
|
reason = FascistHistory (pass, pw);
|
2009-04-29 02:25:10 +05:30
|
|
|
#else /* !HAVE_LIBCRACK_PW */
|
2007-10-07 17:14:59 +05:30
|
|
|
const char *FascistHistory (const char *, int);
|
|
|
|
|
|
|
|
reason = FascistHistory (pass, pw->pw_uid);
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* !HAVE_LIBCRACK_PW */
|
2008-08-31 22:59:51 +05:30
|
|
|
if (NULL != reason) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) printf (_("Bad password: %s. "), reason);
|
|
|
|
return true;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* HAVE_LIBCRACK_HIST */
|
2010-08-22 18:19:07 +05:30
|
|
|
return false;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* new_password - validate old password and replace with new (both old and
|
|
|
|
* new in global "char crypt_passwd[128]")
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:17:01 +05:30
|
|
|
static int new_password (const struct passwd *pw)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:14:59 +05:30
|
|
|
char *clear; /* Pointer to clear text */
|
|
|
|
char *cipher; /* Pointer to cipher text */
|
2013-08-04 02:37:06 +05:30
|
|
|
const char *salt; /* Pointer to new salt */
|
2022-09-28 00:51:35 +05:30
|
|
|
char *cp; /* Pointer to agetpass() response */
|
2007-10-07 17:14:59 +05:30
|
|
|
char orig[200]; /* Original password */
|
|
|
|
char pass[200]; /* New password */
|
|
|
|
int i; /* Counter for retries */
|
2010-08-22 18:19:07 +05:30
|
|
|
bool warned;
|
2007-11-20 03:44:19 +05:30
|
|
|
int pass_max_len = -1;
|
2010-08-22 01:25:46 +05:30
|
|
|
const char *method;
|
2007-10-07 17:14:59 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef HAVE_LIBCRACK_HIST
|
2007-10-07 17:14:59 +05:30
|
|
|
int HistUpdate (const char *, const char *);
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* HAVE_LIBCRACK_HIST */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Authenticate the user. The user will be prompted for their own
|
|
|
|
* password.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
|
2010-08-22 18:19:07 +05:30
|
|
|
if (!amroot && ('\0' != crypt_passwd[0])) {
|
2022-09-28 00:51:35 +05:30
|
|
|
clear = agetpass (_("Old password: "));
|
2008-08-31 22:59:51 +05:30
|
|
|
if (NULL == clear) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-08-31 22:59:51 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
cipher = pw_encrypt (clear, crypt_passwd);
|
2013-08-04 02:37:06 +05:30
|
|
|
|
|
|
|
if (NULL == cipher) {
|
2022-09-28 00:51:35 +05:30
|
|
|
erase_pass (clear);
|
2013-08-04 02:37:06 +05:30
|
|
|
fprintf (stderr,
|
|
|
|
_("%s: failed to crypt password with previous salt: %s\n"),
|
|
|
|
Prog, strerror (errno));
|
|
|
|
SYSLOG ((LOG_INFO,
|
|
|
|
"Failed to crypt password with previous salt of user '%s'",
|
|
|
|
pw->pw_name));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp (cipher, crypt_passwd) != 0) {
|
2022-09-28 00:51:35 +05:30
|
|
|
erase_pass (clear);
|
2010-08-22 18:19:07 +05:30
|
|
|
strzero (cipher);
|
2007-10-07 17:17:01 +05:30
|
|
|
SYSLOG ((LOG_WARN, "incorrect password for %s",
|
2010-08-22 18:19:07 +05:30
|
|
|
pw->pw_name));
|
|
|
|
(void) sleep (1);
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("Incorrect password for %s.\n"),
|
|
|
|
pw->pw_name);
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
STRFCPY (orig, clear);
|
2022-09-28 00:51:35 +05:30
|
|
|
erase_pass (clear);
|
2007-10-07 17:14:59 +05:30
|
|
|
strzero (cipher);
|
2007-10-07 17:14:02 +05:30
|
|
|
} else {
|
|
|
|
orig[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Get the new password. The user is prompted for the new password
|
|
|
|
* and has five tries to get it right. The password will be tested
|
|
|
|
* for strength, unless it is the root user. This provides an escape
|
2007-10-07 17:14:02 +05:30
|
|
|
* for initial login passwords.
|
|
|
|
*/
|
2010-08-22 01:25:46 +05:30
|
|
|
method = getdef_str ("ENCRYPT_METHOD");
|
|
|
|
if (NULL == method) {
|
2008-08-31 22:59:51 +05:30
|
|
|
if (!getdef_bool ("MD5_CRYPT_ENAB")) {
|
2007-11-20 03:44:19 +05:30
|
|
|
pass_max_len = getdef_num ("PASS_MAX_LEN", 8);
|
2008-08-31 22:59:51 +05:30
|
|
|
}
|
2007-11-20 03:44:19 +05:30
|
|
|
} else {
|
2008-08-31 22:59:51 +05:30
|
|
|
if ( (strcmp (method, "MD5") == 0)
|
* configure.in: New configure option: --with-sha-crypt enabled by
default. Keeping the feature enabled is safe. Disabling it permits
to disable the references to the SHA256 and SHA512 password
encryption algorithms from the usage help and manuals (in addition
to the support for these algorithms in the code).
* libmisc/obscure.c, libmisc/salt.c, src/newusers.c,
src/chpasswd.c, src/chgpasswd.c, src/passwd.c: ENCRYPT_METHOD is
always supported in login.defs. Remove the ENCRYPTMETHOD_SELECT
preprocessor condition.
* libmisc/obscure.c, libmisc/salt.c, src/newusers.c,
src/chpasswd.c, src/chgpasswd.c, src/passwd.c: Disable SHA256 and
SHA512 if USE_SHA_CRYPT is not defined (this corresponds to a
subset of the ENCRYPTMETHOD_SELECT sections).
2007-11-24 18:38:08 +05:30
|
|
|
#ifdef USE_SHA_CRYPT
|
2008-08-31 22:59:51 +05:30
|
|
|
|| (strcmp (method, "SHA256") == 0)
|
|
|
|
|| (strcmp (method, "SHA512") == 0)
|
2019-09-17 00:24:56 +05:30
|
|
|
#endif /* USE_SHA_CRYPT */
|
|
|
|
#ifdef USE_BCRYPT
|
|
|
|
|| (strcmp (method, "BCRYPT") == 0)
|
2020-03-05 08:21:39 +05:30
|
|
|
#endif /* USE_BCRYPT*/
|
2020-12-28 01:39:25 +05:30
|
|
|
#ifdef USE_YESCRYPT
|
|
|
|
|| (strcmp (method, "YESCRYPT") == 0)
|
|
|
|
#endif /* USE_YESCRYPT*/
|
2019-09-17 00:24:56 +05:30
|
|
|
|
2008-08-31 22:59:51 +05:30
|
|
|
) {
|
2007-11-20 03:44:19 +05:30
|
|
|
pass_max_len = -1;
|
2008-08-31 22:59:51 +05:30
|
|
|
} else {
|
2007-11-20 03:44:19 +05:30
|
|
|
pass_max_len = getdef_num ("PASS_MAX_LEN", 8);
|
2008-08-31 22:59:51 +05:30
|
|
|
}
|
2007-11-20 03:44:19 +05:30
|
|
|
}
|
|
|
|
if (!qflg) {
|
|
|
|
if (pass_max_len == -1) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) printf (_(
|
2007-11-20 03:44:19 +05:30
|
|
|
"Enter the new password (minimum of %d characters)\n"
|
|
|
|
"Please use a combination of upper and lower case letters and numbers.\n"),
|
|
|
|
getdef_num ("PASS_MIN_LEN", 5));
|
|
|
|
} else {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) printf (_(
|
2007-11-20 03:44:19 +05:30
|
|
|
"Enter the new password (minimum of %d, maximum of %d characters)\n"
|
|
|
|
"Please use a combination of upper and lower case letters and numbers.\n"),
|
|
|
|
getdef_num ("PASS_MIN_LEN", 5), pass_max_len);
|
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2010-08-22 18:19:07 +05:30
|
|
|
warned = false;
|
2007-10-07 17:14:59 +05:30
|
|
|
for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {
|
2022-09-28 00:51:35 +05:30
|
|
|
cp = agetpass (_("New password: "));
|
2008-08-31 22:59:51 +05:30
|
|
|
if (NULL == cp) {
|
2007-10-07 17:14:59 +05:30
|
|
|
memzero (orig, sizeof orig);
|
2022-04-25 15:47:40 +05:30
|
|
|
memzero (pass, sizeof pass);
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
|
|
|
}
|
2008-08-31 22:59:51 +05:30
|
|
|
if (warned && (strcmp (pass, cp) != 0)) {
|
2010-08-22 18:19:07 +05:30
|
|
|
warned = false;
|
2008-08-31 22:59:51 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
STRFCPY (pass, cp);
|
2022-09-28 00:51:35 +05:30
|
|
|
erase_pass (cp);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
if (!amroot && (!obscure (orig, pass, pw) || reuse (pass, pw))) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) puts (_("Try again."));
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
|
|
|
}
|
2007-10-07 17:17:01 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* If enabled, warn about weak passwords even if you are
|
2021-09-13 21:53:17 +05:30
|
|
|
* root (enter this password again to use it anyway).
|
2007-10-07 17:14:59 +05:30
|
|
|
* --marekm
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN")
|
|
|
|
&& (!obscure (orig, pass, pw) || reuse (pass, pw))) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) puts (_("\nWarning: weak password (enter it again to use it anyway)."));
|
|
|
|
warned = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
continue;
|
|
|
|
}
|
2022-09-28 00:51:35 +05:30
|
|
|
cp = agetpass (_("Re-enter new password: "));
|
2008-08-31 22:59:51 +05:30
|
|
|
if (NULL == cp) {
|
2007-10-07 17:14:59 +05:30
|
|
|
memzero (orig, sizeof orig);
|
2022-04-25 15:47:40 +05:30
|
|
|
memzero (pass, sizeof pass);
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
|
|
|
}
|
2008-08-31 22:59:51 +05:30
|
|
|
if (strcmp (cp, pass) != 0) {
|
2022-09-28 00:51:35 +05:30
|
|
|
erase_pass (cp);
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fputs (_("They don't match; try again.\n"), stderr);
|
2008-08-31 22:59:51 +05:30
|
|
|
} else {
|
2022-09-28 00:51:35 +05:30
|
|
|
erase_pass (cp);
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
memzero (orig, sizeof orig);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (i == 0) {
|
2007-10-07 17:14:59 +05:30
|
|
|
memzero (pass, sizeof pass);
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Encrypt the password, then wipe the cleartext password.
|
|
|
|
*/
|
2013-08-04 02:37:06 +05:30
|
|
|
salt = crypt_make_salt (NULL, NULL);
|
|
|
|
cp = pw_encrypt (pass, salt);
|
2007-10-07 17:14:59 +05:30
|
|
|
memzero (pass, sizeof pass);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2013-08-04 02:37:06 +05:30
|
|
|
if (NULL == cp) {
|
|
|
|
fprintf (stderr,
|
|
|
|
_("%s: failed to crypt password with salt '%s': %s\n"),
|
|
|
|
Prog, salt, strerror (errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef HAVE_LIBCRACK_HIST
|
2007-10-07 17:14:59 +05:30
|
|
|
HistUpdate (pw->pw_name, crypt_passwd);
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* HAVE_LIBCRACK_HIST */
|
2007-10-07 17:14:59 +05:30
|
|
|
STRFCPY (crypt_passwd, cp);
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check_password - test a password to see if it can be changed
|
|
|
|
*
|
|
|
|
* check_password() sees if the invoker has permission to change the
|
|
|
|
* password for the given user.
|
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
static void check_password (const struct passwd *pw, const struct spwd *sp)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
* src/newgrp.c: Limit the scope of variable pid.
* src/login_nopam.c: Limit the scope of variables end, lineno, i,
str_len.
* src/logoutd.c: Limit the scope of variable c.
* src/vipw.c: Re-indent.
* src/vipw.c: Close the file after the creation of the backup.
* src/useradd.c (set_default): Close input file on failure.
* src/useradd.c: Limit the scope of variables spool, file, fd, gr,
gid, mode.
* src/passwd.c: Limit the scope of variables last and ok.
* src/chage.c: Fix typo (non breaking space).
* src/login.c: Limit the scope of variables erasechar killchar, c,
failed.
* src/groups.c: Limit the scope of variable ngroups, pri_grp, i.
* src/id.c: Limit the scope of variable i.
2010-03-23 16:56:34 +05:30
|
|
|
time_t now;
|
2007-10-07 17:14:02 +05:30
|
|
|
int exp_status;
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
exp_status = isexpired (pw, sp);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* If not expired and the "change only if expired" option (idea from
|
|
|
|
* PAM) was specified, do nothing. --marekm
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2008-08-31 22:59:51 +05:30
|
|
|
if (kflg && (0 == exp_status)) {
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_SUCCESS);
|
2008-08-31 22:59:51 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* Root can change any password any time.
|
|
|
|
*/
|
2008-06-10 23:20:21 +05:30
|
|
|
if (amroot) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return;
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-14 02:39:14 +05:30
|
|
|
(void) time (&now);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Expired accounts cannot be changed ever. Passwords which are
|
|
|
|
* locked may not be changed. Passwords where min > max may not be
|
|
|
|
* changed. Passwords which have been inactive too long cannot be
|
|
|
|
* changed.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
if ( (sp->sp_pwdp[0] == '!')
|
|
|
|
|| (exp_status > 1)
|
|
|
|
|| ( (sp->sp_max >= 0)
|
|
|
|
&& (sp->sp_min > sp->sp_max))) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("The password for %s cannot be changed.\n"),
|
|
|
|
sp->sp_namp);
|
* src/chfn.c, src/chsh.c, src/groupdel.c, src/groupmems.c,
src/groupmod.c, src/grpck.c, src/login.c, src/logoutd.c,
src/newgrp.c, src/newusers.c, src/passwd.c, src/pwck.c,
src/suauth.c, src/useradd.c, src/userdel.c, src/usermod.c,
src/vipw.c: Complete the switch from the `' quotation style to ''.
Do it also in SYSLOG messages. Quote some parameters. All this
permits to merge some messages.
2008-08-06 21:21:52 +05:30
|
|
|
SYSLOG ((LOG_WARN, "password locked for '%s'", sp->sp_namp));
|
2007-10-07 17:14:59 +05:30
|
|
|
closelog ();
|
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Passwords may only be changed after sp_min time is up.
|
|
|
|
*/
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
if (sp->sp_lstchg > 0) {
|
2011-11-20 03:30:00 +05:30
|
|
|
time_t ok;
|
|
|
|
ok = (time_t) sp->sp_lstchg * SCALE;
|
|
|
|
if (sp->sp_min > 0) {
|
|
|
|
ok += (time_t) sp->sp_min * SCALE;
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
if (now < ok) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("The password for %s cannot be changed yet.\n"),
|
|
|
|
pw->pw_name);
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
SYSLOG ((LOG_WARN, "now < minimum age for '%s'", pw->pw_name));
|
|
|
|
closelog ();
|
|
|
|
exit (E_NOPERM);
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
#endif /* !USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2010-08-22 18:19:07 +05:30
|
|
|
static /*@observer@*/const char *pw_status (const char *pass)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2008-06-10 23:20:21 +05:30
|
|
|
if (*pass == '*' || *pass == '!') {
|
2007-10-07 17:14:02 +05:30
|
|
|
return "L";
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
|
|
|
if (*pass == '\0') {
|
2007-10-07 17:14:02 +05:30
|
|
|
return "NP";
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
return "P";
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* print_status - print current password status
|
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
static void print_status (const struct passwd *pw)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2021-12-22 20:02:17 +05:30
|
|
|
char date[80];
|
2007-10-07 17:14:02 +05:30
|
|
|
struct spwd *sp;
|
|
|
|
|
* lib/prototypes.h, configure.in, libmisc/Makefile.am,
libmisc/xgetXXbyYY.c, libmisc/xgetpwnam.c, libmisc/xgetpwuid.c,
libmisc/xgetgrnam.c, libmisc/xgetgrgid.c, libmisc/xgetspnam.c:
Added functions xgetpwnam(), xgetpwuid(), xgetgrnam(),
xgetgrgid(), and xgetspnam(). They allocate memory for the
returned structure and are more robust to successive calls. They
are implemented with the libc's getxxyyy_r() functions if
available.
* libmisc/limits.c, libmisc/entry.c, libmisc/chowntty.c,
libmisc/addgrps.c, libmisc/myname.c, libmisc/rlogin.c,
libmisc/pwdcheck.c, src/newgrp.c, src/login_nopam.c,
src/userdel.c, src/lastlog.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/chfn.c, src/groupmems.c,
src/usermod.c, src/expiry.c, src/groupdel.c, src/chgpasswd.c,
src/su.c, src/useradd.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/suauth.c,
src/faillog.c, src/groups.c, src/chsh.c, src/id.c: Review all the
usage of one of the getpwnam(), getpwuid(), getgrnam(),
getgrgid(), and getspnam() functions. It was noticed on
http://bugs.debian.org/341230 that chfn and chsh use a passwd
structure after calling a pam function, which result in using
information from the passwd structure requested by pam, not the
original one. It is much easier to use the new xget... functions
to avoid these issues. I've checked which call to the original
get... functions could be left (reducing the scope of the
structure if possible), and I've left comments to ease future
reviews (e.g. /* local, no need for xgetpwnam */).
Note: the getpwent/getgrent calls should probably be checked also.
* src/groupdel.c, src/expiry.c: Fix typos in comments.
* src/groupmod.c: Re-indent.
* libmisc/Makefile.am, lib/groupmem.c, lib/groupio.c, lib/pwmem.c,
lib/pwio.c, lib/shadowmem.c, lib/shadowio.c: Move the __<xx>_dup
functions (used by the xget... functions) from the <xx>io.c files
to the new <xx>mem.c files. This avoid linking some utils against
the SELinux library.
2007-11-19 04:45:26 +05:30
|
|
|
sp = getspnam (pw->pw_name); /* local, no need for xgetspnam */
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL != sp) {
|
2021-12-22 20:02:17 +05:30
|
|
|
date_to_str (sizeof(date), date, sp->sp_lstchg * SCALE),
|
2011-07-14 19:33:19 +05:30
|
|
|
(void) printf ("%s %s %s %lld %lld %lld %lld\n",
|
2010-08-22 18:19:07 +05:30
|
|
|
pw->pw_name,
|
|
|
|
pw_status (sp->sp_pwdp),
|
2021-12-22 20:02:17 +05:30
|
|
|
date,
|
2011-07-14 19:33:19 +05:30
|
|
|
((long long)sp->sp_min * SCALE) / DAY,
|
|
|
|
((long long)sp->sp_max * SCALE) / DAY,
|
|
|
|
((long long)sp->sp_warn * SCALE) / DAY,
|
|
|
|
((long long)sp->sp_inact * SCALE) / DAY);
|
2021-08-03 23:33:46 +05:30
|
|
|
} else if (NULL != pw->pw_passwd) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) printf ("%s %s\n",
|
|
|
|
pw->pw_name, pw_status (pw->pw_passwd));
|
2021-08-03 23:33:46 +05:30
|
|
|
} else {
|
|
|
|
(void) fprintf(stderr, _("%s: malformed password data obtained for user %s\n"),
|
|
|
|
Prog, pw->pw_name);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN
|
|
|
|
static void
|
|
|
|
fail_exit (int status)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2008-08-22 07:54:29 +05:30
|
|
|
if (pw_locked) {
|
|
|
|
if (pw_unlock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
|
2008-08-22 07:54:29 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
|
|
|
/* continue */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spw_locked) {
|
|
|
|
if (spw_unlock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
|
2008-08-22 07:54:29 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
|
|
|
|
/* continue */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (status);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN
|
|
|
|
static void
|
|
|
|
oom (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr, _("%s: out of memory\n"), Prog);
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
static char *update_crypt_pw (char *cp)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
#ifndef USE_PAM
|
2008-06-10 23:20:21 +05:30
|
|
|
if (do_update_pwd) {
|
2010-08-22 18:19:07 +05:30
|
|
|
cp = xstrdup (crypt_passwd);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* !USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-10 23:20:21 +05:30
|
|
|
if (dflg) {
|
2008-01-07 00:56:58 +05:30
|
|
|
*cp = '\0';
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-11-18 03:35:31 +05:30
|
|
|
if (uflg && *cp == '!') {
|
|
|
|
if (cp[1] == '\0') {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: unlocking the password would result in a passwordless account.\n"
|
|
|
|
"You should set a password with usermod -p to unlock the password of this account.\n"),
|
|
|
|
Prog);
|
2009-05-09 18:44:31 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-11-18 03:35:31 +05:30
|
|
|
} else {
|
|
|
|
cp++;
|
|
|
|
}
|
2009-05-22 19:02:26 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (lflg && *cp != '!') {
|
2023-02-05 03:11:18 +05:30
|
|
|
char *newpw = XMALLOCARRAY (strlen (cp) + 2, char);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
strcpy (newpw, "!");
|
|
|
|
strcat (newpw, cp);
|
Fix covscan RESOURCE_LEAK
Error: RESOURCE_LEAK (CWE-772): [#def1]
shadow-4.8.1/lib/commonio.c:320: alloc_fn: Storage is returned from allocation function "fopen_set_perms".
shadow-4.8.1/lib/commonio.c:320: var_assign: Assigning: "bkfp" = storage returned from "fopen_set_perms(backup, "w", &sb)".
shadow-4.8.1/lib/commonio.c:329: noescape: Resource "bkfp" is not freed or pointed-to in "putc".
shadow-4.8.1/lib/commonio.c:334: noescape: Resource "bkfp" is not freed or pointed-to in "fflush".
shadow-4.8.1/lib/commonio.c:339: noescape: Resource "bkfp" is not freed or pointed-to in "fileno".
shadow-4.8.1/lib/commonio.c:342: leaked_storage: Variable "bkfp" going out of scope leaks the storage it points to.
340| || (fclose (bkfp) != 0)) {
341| /* FIXME: unlink the backup file? */
342|-> return -1;
343| }
344|
Error: RESOURCE_LEAK (CWE-772): [#def2]
shadow-4.8.1/libmisc/addgrps.c:69: alloc_fn: Storage is returned from allocation function "malloc".
shadow-4.8.1/libmisc/addgrps.c:69: var_assign: Assigning: "grouplist" = storage returned from "malloc(i * 4UL)".
shadow-4.8.1/libmisc/addgrps.c:73: noescape: Resource "grouplist" is not freed or pointed-to in "getgroups". [Note: The source code implementation of the function has been overridden by a builtin model.]
shadow-4.8.1/libmisc/addgrps.c:126: leaked_storage: Variable "grouplist" going out of scope leaks the storage it points to.
124| }
125|
126|-> return 0;
127| }
128| #else /* HAVE_SETGROUPS && !USE_PAM */
Error: RESOURCE_LEAK (CWE-772): [#def3]
shadow-4.8.1/libmisc/chowntty.c:62: alloc_fn: Storage is returned from allocation function "getgr_nam_gid".
shadow-4.8.1/libmisc/chowntty.c:62: var_assign: Assigning: "grent" = storage returned from "getgr_nam_gid(getdef_str("TTYGROUP"))".
shadow-4.8.1/libmisc/chowntty.c:98: leaked_storage: Variable "grent" going out of scope leaks the storage it points to.
96| */
97| #endif
98|-> }
99|
Error: RESOURCE_LEAK (CWE-772): [#def4]
shadow-4.8.1/libmisc/copydir.c:742: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.]
shadow-4.8.1/libmisc/copydir.c:742: var_assign: Assigning: "ifd" = handle returned from "open(src, 0)".
shadow-4.8.1/libmisc/copydir.c:748: leaked_handle: Handle variable "ifd" going out of scope leaks the handle.
746| #ifdef WITH_SELINUX
747| if (set_selinux_file_context (dst, NULL) != 0) {
748|-> return -1;
749| }
750| #endif /* WITH_SELINUX */
Error: RESOURCE_LEAK (CWE-772): [#def5]
shadow-4.8.1/libmisc/copydir.c:751: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.]
shadow-4.8.1/libmisc/copydir.c:751: var_assign: Assigning: "ofd" = handle returned from "open(dst, 577, statp->st_mode & 0xfffU)".
shadow-4.8.1/libmisc/copydir.c:752: noescape: Resource "ofd" is not freed or pointed-to in "fchown_if_needed".
shadow-4.8.1/libmisc/copydir.c:775: leaked_handle: Handle variable "ofd" going out of scope leaks the handle.
773| ) {
774| (void) close (ifd);
775|-> return -1;
776| }
777|
Error: RESOURCE_LEAK (CWE-772): [#def7]
shadow-4.8.1/libmisc/idmapping.c:188: alloc_fn: Storage is returned from allocation function "xmalloc".
shadow-4.8.1/libmisc/idmapping.c:188: var_assign: Assigning: "buf" = storage returned from "xmalloc(bufsize)".
shadow-4.8.1/libmisc/idmapping.c:188: var_assign: Assigning: "pos" = "buf".
shadow-4.8.1/libmisc/idmapping.c:213: noescape: Resource "buf" is not freed or pointed-to in "write".
shadow-4.8.1/libmisc/idmapping.c:219: leaked_storage: Variable "pos" going out of scope leaks the storage it points to.
shadow-4.8.1/libmisc/idmapping.c:219: leaked_storage: Variable "buf" going out of scope leaks the storage it points to.
217| }
218| close(fd);
219|-> }
Error: RESOURCE_LEAK (CWE-772): [#def8]
shadow-4.8.1/libmisc/list.c:211: alloc_fn: Storage is returned from allocation function "xstrdup".
shadow-4.8.1/libmisc/list.c:211: var_assign: Assigning: "members" = storage returned from "xstrdup(comma)".
shadow-4.8.1/libmisc/list.c:217: var_assign: Assigning: "cp" = "members".
shadow-4.8.1/libmisc/list.c:218: noescape: Resource "cp" is not freed or pointed-to in "strchr".
shadow-4.8.1/libmisc/list.c:244: leaked_storage: Variable "cp" going out of scope leaks the storage it points to.
shadow-4.8.1/libmisc/list.c:244: leaked_storage: Variable "members" going out of scope leaks the storage it points to.
242| if ('\0' == *members) {
243| *array = (char *) 0;
244|-> return array;
245| }
246|
Error: RESOURCE_LEAK (CWE-772): [#def11]
shadow-4.8.1/libmisc/myname.c:61: alloc_fn: Storage is returned from allocation function "xgetpwnam".
shadow-4.8.1/libmisc/myname.c:61: var_assign: Assigning: "pw" = storage returned from "xgetpwnam(cp)".
shadow-4.8.1/libmisc/myname.c:67: leaked_storage: Variable "pw" going out of scope leaks the storage it points to.
65| }
66|
67|-> return xgetpwuid (ruid);
68| }
69|
Error: RESOURCE_LEAK (CWE-772): [#def12]
shadow-4.8.1/libmisc/user_busy.c:260: alloc_fn: Storage is returned from allocation function "opendir".
shadow-4.8.1/libmisc/user_busy.c:260: var_assign: Assigning: "task_dir" = storage returned from "opendir(task_path)".
shadow-4.8.1/libmisc/user_busy.c:262: noescape: Resource "task_dir" is not freed or pointed-to in "readdir".
shadow-4.8.1/libmisc/user_busy.c:278: leaked_storage: Variable "task_dir" going out of scope leaks the storage it points to.
276| _("%s: user %s is currently used by process %d\n"),
277| Prog, name, pid);
278|-> return 1;
279| }
280| }
Error: RESOURCE_LEAK (CWE-772): [#def20]
shadow-4.8.1/src/newgrp.c:162: alloc_fn: Storage is returned from allocation function "xgetspnam".
shadow-4.8.1/src/newgrp.c:162: var_assign: Assigning: "spwd" = storage returned from "xgetspnam(pwd->pw_name)".
shadow-4.8.1/src/newgrp.c:234: leaked_storage: Variable "spwd" going out of scope leaks the storage it points to.
232| }
233|
234|-> return;
235|
236| failure:
Error: RESOURCE_LEAK (CWE-772): [#def21]
shadow-4.8.1/src/passwd.c:530: alloc_fn: Storage is returned from allocation function "xstrdup".
shadow-4.8.1/src/passwd.c:530: var_assign: Assigning: "cp" = storage returned from "xstrdup(crypt_passwd)".
shadow-4.8.1/src/passwd.c:551: noescape: Resource "cp" is not freed or pointed-to in "strlen".
shadow-4.8.1/src/passwd.c:554: noescape: Resource "cp" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.]
shadow-4.8.1/src/passwd.c:555: overwrite_var: Overwriting "cp" in "cp = newpw" leaks the storage that "cp" points to.
553| strcpy (newpw, "!");
554| strcat (newpw, cp);
555|-> cp = newpw;
556| }
557| return cp;
2021-06-14 16:09:48 +05:30
|
|
|
#ifndef USE_PAM
|
|
|
|
if (do_update_pwd) {
|
|
|
|
free (cp);
|
|
|
|
}
|
|
|
|
#endif /* USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
cp = newpw;
|
|
|
|
}
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
static void update_noshadow (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
const struct passwd *pw;
|
|
|
|
struct passwd *npw;
|
2007-10-07 17:14:59 +05:30
|
|
|
|
2008-06-10 23:20:21 +05:30
|
|
|
if (pw_lock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: cannot lock %s; try again later.\n"),
|
|
|
|
Prog, pw_dbname ());
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_PWDBUSY);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-08-22 07:54:29 +05:30
|
|
|
pw_locked = true;
|
2015-02-27 18:47:25 +05:30
|
|
|
if (pw_open (O_CREAT | O_RDWR) == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: cannot open %s\n"),
|
|
|
|
Prog, pw_dbname ());
|
* src/chfn.c: Do not exit on pw_unlock failures.
* src/grpconv.c, src/grpunconv.c, src/pwconv.c, src/pwunconv.c,
src/vipw.c: Open syslog with the right identification name.
* src/vipw.c: Log unlock errors to syslog.
* src/vipw.c: Log edits to syslog.
* src/chage.c, src/chfn.c, src/chsh.c, src/gpasswd.c,
src/groupadd.c, src/groupdel.c, src/groupmod.c, src/grpconv.c,
src/grpunconv.c, src/passwd.c, src/pwck.c, src/pwunconv.c,
src/useradd.c, src/usermod.c: Harmonize the syslog levels. Failure
to close or unlock are errors. Failure to open files are warnings.
2008-08-22 08:00:33 +05:30
|
|
|
SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ()));
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_MISSING);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
pw = pw_locate (name);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == pw) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: user '%s' does not exist in %s\n"),
|
|
|
|
Prog, name, pw_dbname ());
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
npw = __pw_dup (pw);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == npw) {
|
2007-10-07 17:14:59 +05:30
|
|
|
oom ();
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
npw->pw_passwd = update_crypt_pw (npw->pw_passwd);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (pw_update (npw) == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
|
|
|
Prog, pw_dbname (), npw->pw_name);
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
if (pw_close () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failure while writing changes to %s\n"),
|
|
|
|
Prog, pw_dbname ());
|
* lib/groupio.c, lib/groupio.h, lib/pwio.c, lib/pwio.h,
lib/sgroupio.c, lib/sgroupio.h, lib/shadowio.c, lib/shadowio.h:
Added *_dbname() functions to retrieve the name of the databases.
* lib/groupio.c, lib/groupio.h, lib/pwio.c, lib/pwio.h,
lib/sgroupio.c, lib/sgroupio.h, lib/shadowio.c, lib/shadowio.h:
*_name() functions renamed *setname().
* src/grpck.c, src/pwck.c: Likewise.
* lib/groupio.h, lib/pwio.h, lib/sgroupio.h, lib/shadowio.h: Added
the name of the arguments to the prototypes.
* src/chage, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/gpasswd.c, src/groupadd.c, src/groupdel.c,
src/groupmod.c, src/grpck.c, src/grpconv.c, src/grpunconv.c,
src/newusers.c, src/passwd.c, src/pwck.c, src/pwconv.c,
src/pwunconv.c, src/useradd.c, src/userdel.c, src/usermod.c:
Harmonize the erro & syslog messages in case of failure of the
*_lock(), *_open(), *_close(), *_unlock(), *_remove() functions.
* src/chgpasswd.c, src/chpasswd.c, src/usermod.c: Avoid
capitalized messages.
* src/chpasswd.c, src/useradd.c, src/usermod.c: Harmonize messages
in case of inexistent entries.
* src/usermod.c: Harmonize messages in case of already existing
entries.
* src/newusers.c, src/useradd.c: Simplify PAM error handling.
* src/useradd.c: Report failures to unlock files (stderr, syslog,
and audit). But do not fail (continue).
* src/useradd.c (open_files): Do not report to syslog & audit
failures to lock or open the databases. This might be harmless,
and the logs were not already informed that a change was
requested.
* src/usermod.c: It's not the account which is unlocked, but its
password.
2008-08-06 21:27:31 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-08-22 07:54:29 +05:30
|
|
|
if (pw_unlock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failed to unlock %s\n"),
|
|
|
|
Prog, pw_dbname ());
|
2008-08-22 07:54:29 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
|
|
|
/* continue */
|
|
|
|
}
|
|
|
|
pw_locked = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
static void update_shadow (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
const struct spwd *sp;
|
|
|
|
struct spwd *nsp;
|
|
|
|
|
2008-06-10 23:20:21 +05:30
|
|
|
if (spw_lock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: cannot lock %s; try again later.\n"),
|
|
|
|
Prog, spw_dbname ());
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_PWDBUSY);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-08-22 07:54:29 +05:30
|
|
|
spw_locked = true;
|
2015-02-27 18:47:25 +05:30
|
|
|
if (spw_open (O_CREAT | O_RDWR) == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: cannot open %s\n"),
|
|
|
|
Prog, spw_dbname ());
|
* src/chfn.c: Do not exit on pw_unlock failures.
* src/grpconv.c, src/grpunconv.c, src/pwconv.c, src/pwunconv.c,
src/vipw.c: Open syslog with the right identification name.
* src/vipw.c: Log unlock errors to syslog.
* src/vipw.c: Log edits to syslog.
* src/chage.c, src/chfn.c, src/chsh.c, src/gpasswd.c,
src/groupadd.c, src/groupdel.c, src/groupmod.c, src/grpconv.c,
src/grpunconv.c, src/passwd.c, src/pwck.c, src/pwunconv.c,
src/useradd.c, src/usermod.c: Harmonize the syslog levels. Failure
to close or unlock are errors. Failure to open files are warnings.
2008-08-22 08:00:33 +05:30
|
|
|
SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ()));
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
sp = spw_locate (name);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == sp) {
|
2007-10-07 17:14:59 +05:30
|
|
|
/* Try to update the password in /etc/passwd instead. */
|
2008-08-22 07:54:29 +05:30
|
|
|
(void) spw_close ();
|
2007-10-07 17:14:59 +05:30
|
|
|
update_noshadow ();
|
2008-08-22 07:54:29 +05:30
|
|
|
if (spw_unlock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failed to unlock %s\n"),
|
|
|
|
Prog, spw_dbname ());
|
2008-08-22 07:54:29 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
|
|
|
|
/* continue */
|
|
|
|
}
|
|
|
|
spw_locked = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
return;
|
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
nsp = __spw_dup (sp);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == nsp) {
|
2007-10-07 17:14:59 +05:30
|
|
|
oom ();
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (xflg) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nsp->sp_max = (age_max * DAY) / SCALE;
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
|
|
|
if (nflg) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nsp->sp_min = (age_min * DAY) / SCALE;
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
|
|
|
if (wflg) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nsp->sp_warn = (warn * DAY) / SCALE;
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
|
|
|
if (iflg) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nsp->sp_inact = (inact * DAY) / SCALE;
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2009-04-06 03:34:31 +05:30
|
|
|
#ifndef USE_PAM
|
2008-06-10 23:20:21 +05:30
|
|
|
if (do_update_age) {
|
2023-02-01 18:20:48 +05:30
|
|
|
nsp->sp_lstchg = gettime () / SCALE;
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
if (0 == nsp->sp_lstchg) {
|
|
|
|
/* Better disable aging than requiring a password
|
|
|
|
* change */
|
|
|
|
nsp->sp_lstchg = -1;
|
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* !USE_PAM */
|
2007-10-07 17:17:01 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Force change on next login, like SunOS 4.x passwd -e or Solaris
|
|
|
|
* 2.x passwd -f. Solaris 2.x seems to do the same thing (set
|
|
|
|
* sp_lstchg to 0).
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
if (eflg) {
|
2007-10-07 17:14:02 +05:30
|
|
|
nsp->sp_lstchg = 0;
|
* libmisc/pwd2spwd.c, src/chpasswd.c, src/newusers.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/useradd.c,
src/usermod.c: On Jan 01, 1970, do not set the sp_lstchg field to
0 (which means that the password shall be changed during the next
login), but use -1 (password aging disabled).
* src/passwd.c: Do not check sp_min if sp_lstchg is null or -1.
2009-04-06 02:53:27 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-10 23:20:21 +05:30
|
|
|
if (spw_update (nsp) == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
|
|
|
Prog, spw_dbname (), nsp->sp_namp);
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
if (spw_close () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failure while writing changes to %s\n"),
|
|
|
|
Prog, spw_dbname ());
|
* lib/groupio.c, lib/groupio.h, lib/pwio.c, lib/pwio.h,
lib/sgroupio.c, lib/sgroupio.h, lib/shadowio.c, lib/shadowio.h:
Added *_dbname() functions to retrieve the name of the databases.
* lib/groupio.c, lib/groupio.h, lib/pwio.c, lib/pwio.h,
lib/sgroupio.c, lib/sgroupio.h, lib/shadowio.c, lib/shadowio.h:
*_name() functions renamed *setname().
* src/grpck.c, src/pwck.c: Likewise.
* lib/groupio.h, lib/pwio.h, lib/sgroupio.h, lib/shadowio.h: Added
the name of the arguments to the prototypes.
* src/chage, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/gpasswd.c, src/groupadd.c, src/groupdel.c,
src/groupmod.c, src/grpck.c, src/grpconv.c, src/grpunconv.c,
src/newusers.c, src/passwd.c, src/pwck.c, src/pwconv.c,
src/pwunconv.c, src/useradd.c, src/userdel.c, src/usermod.c:
Harmonize the erro & syslog messages in case of failure of the
*_lock(), *_open(), *_close(), *_unlock(), *_remove() functions.
* src/chgpasswd.c, src/chpasswd.c, src/usermod.c: Avoid
capitalized messages.
* src/chpasswd.c, src/useradd.c, src/usermod.c: Harmonize messages
in case of inexistent entries.
* src/usermod.c: Harmonize messages in case of already existing
entries.
* src/newusers.c, src/useradd.c: Simplify PAM error handling.
* src/useradd.c: Report failures to unlock files (stderr, syslog,
and audit). But do not fail (continue).
* src/useradd.c (open_files): Do not report to syslog & audit
failures to lock or open the databases. This might be harmless,
and the logs were not already informed that a change was
requested.
* src/usermod.c: It's not the account which is unlocked, but its
password.
2008-08-06 21:27:31 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
|
2007-10-07 17:14:59 +05:30
|
|
|
fail_exit (E_FAILURE);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-08-22 07:54:29 +05:30
|
|
|
if (spw_unlock () == 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: failed to unlock %s\n"),
|
|
|
|
Prog, spw_dbname ());
|
2008-08-22 07:54:29 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
|
|
|
|
/* continue */
|
|
|
|
}
|
|
|
|
spw_locked = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* passwd - change a user's password file information
|
|
|
|
*
|
2007-10-07 17:14:59 +05:30
|
|
|
* This command controls the password file and commands which are used
|
|
|
|
* to modify it.
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
|
|
|
* The valid options are
|
|
|
|
*
|
|
|
|
* -d delete the password for the named account (*)
|
|
|
|
* -e expire the password for the named account (*)
|
|
|
|
* -f execute chfn command to interpret flags
|
2007-10-07 17:17:01 +05:30
|
|
|
* -g execute gpasswd command to interpret flags
|
|
|
|
* -i # set sp_inact to # days (*)
|
2007-10-07 17:14:02 +05:30
|
|
|
* -k change password only if expired
|
2008-08-22 07:46:21 +05:30
|
|
|
* -l lock the password of the named account (*)
|
2007-10-07 17:17:01 +05:30
|
|
|
* -n # set sp_min to # days (*)
|
|
|
|
* -r # change password in # repository
|
|
|
|
* -s execute chsh command to interpret flags
|
|
|
|
* -S show password status of named account
|
2008-08-22 07:46:21 +05:30
|
|
|
* -u unlock the password of the named account (*)
|
2007-10-07 17:17:01 +05:30
|
|
|
* -w # set sp_warn to # days (*)
|
|
|
|
* -x # set sp_max to # days (*)
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
|
|
|
* (*) requires root permission to execute.
|
|
|
|
*
|
|
|
|
* All of the time fields are entered in days and converted to the
|
2007-10-07 17:14:59 +05:30
|
|
|
* appropriate internal format. For finer resolute the chage
|
2007-10-07 17:14:02 +05:30
|
|
|
* command must be used.
|
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
int main (int argc, char **argv)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
const struct passwd *pw; /* Password file entry for user */
|
2007-10-07 17:14:59 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifndef USE_PAM
|
2007-10-07 17:14:59 +05:30
|
|
|
char *cp; /* Miscellaneous character pointing */
|
|
|
|
|
|
|
|
const struct spwd *sp; /* Shadow file entry for user */
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* !USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2011-11-07 00:08:16 +05:30
|
|
|
sanitize_env ();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the program name. The program name is used as a prefix to
|
|
|
|
* most error messages.
|
|
|
|
*/
|
|
|
|
Prog = Basename (argv[0]);
|
2021-11-29 05:07:53 +05:30
|
|
|
log_set_progname(Prog);
|
|
|
|
log_set_logfd(stderr);
|
2011-11-07 00:08:16 +05:30
|
|
|
|
2008-06-10 23:20:21 +05:30
|
|
|
(void) setlocale (LC_ALL, "");
|
|
|
|
(void) bindtextdomain (PACKAGE, LOCALEDIR);
|
|
|
|
(void) textdomain (PACKAGE);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2011-11-07 00:08:16 +05:30
|
|
|
process_root_flag ("-R", argc, argv);
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* The program behaves differently when executed by root than when
|
|
|
|
* executed by a normal user.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
amroot = (getuid () == 0);
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
OPENLOG ("passwd");
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:17:01 +05:30
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Parse the command line options.
|
|
|
|
*/
|
|
|
|
int c;
|
|
|
|
static struct option long_options[] = {
|
* src/chage.c, src/chgpasswd.c, src/chpasswd.c, src/chsh.c,
src/faillog.c, src/gpasswd.c, src/groupadd.c, src/groupdel.c,
src/groupmems.c, src/groupmod.c, src/grpconv.c, src/grpunconv.c,
src/lastlog.c, src/newusers.c, src/passwd.c, src/pwconv.c,
src/pwunconv.c, src/su.c, src/useradd.c, src/userdel.c,
src/usermod.c, src/vipw.c: Align and sort options.
2011-11-07 00:09:59 +05:30
|
|
|
{"all", no_argument, NULL, 'a'},
|
|
|
|
{"delete", no_argument, NULL, 'd'},
|
|
|
|
{"expire", no_argument, NULL, 'e'},
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
{"inactive", required_argument, NULL, 'i'},
|
|
|
|
{"keep-tokens", no_argument, NULL, 'k'},
|
|
|
|
{"lock", no_argument, NULL, 'l'},
|
|
|
|
{"mindays", required_argument, NULL, 'n'},
|
|
|
|
{"quiet", no_argument, NULL, 'q'},
|
|
|
|
{"repository", required_argument, NULL, 'r'},
|
|
|
|
{"root", required_argument, NULL, 'R'},
|
|
|
|
{"status", no_argument, NULL, 'S'},
|
|
|
|
{"unlock", no_argument, NULL, 'u'},
|
|
|
|
{"warndays", required_argument, NULL, 'w'},
|
|
|
|
{"maxdays", required_argument, NULL, 'x'},
|
2007-10-07 17:17:01 +05:30
|
|
|
{NULL, 0, NULL, '\0'}
|
|
|
|
};
|
|
|
|
|
2011-11-07 00:08:16 +05:30
|
|
|
while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:Suw:x:",
|
|
|
|
long_options, NULL)) != -1) {
|
2007-10-07 17:17:01 +05:30
|
|
|
switch (c) {
|
|
|
|
case 'a':
|
2008-06-10 23:20:21 +05:30
|
|
|
aflg = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'd':
|
2008-06-10 23:20:21 +05:30
|
|
|
dflg = true;
|
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'e':
|
2008-06-10 23:20:21 +05:30
|
|
|
eflg = true;
|
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
* src/chage.c, src/chgpasswd.c, src/chpasswd.c, src/chsh.c,
src/faillog.c, src/gpasswd.c, src/groupadd.c, src/groupdel.c,
src/groupmems.c, src/groupmod.c, src/grpconv.c, src/grpunconv.c,
src/lastlog.c, src/newusers.c, src/passwd.c, src/pwconv.c,
src/pwunconv.c, src/su.c, src/useradd.c, src/userdel.c,
src/usermod.c, src/vipw.c: Align and sort options.
2011-11-07 00:09:59 +05:30
|
|
|
case 'h':
|
|
|
|
usage (E_SUCCESS);
|
|
|
|
/*@notreached@*/break;
|
2007-10-07 17:17:01 +05:30
|
|
|
case 'i':
|
2009-04-11 04:04:23 +05:30
|
|
|
if ( (getlong (optarg, &inact) == 0)
|
|
|
|
|| (inact < -1)) {
|
|
|
|
fprintf (stderr,
|
|
|
|
_("%s: invalid numeric argument '%s'\n"),
|
|
|
|
Prog, optarg);
|
|
|
|
usage (E_BAD_ARG);
|
|
|
|
}
|
|
|
|
iflg = true;
|
2008-06-10 23:20:21 +05:30
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
/* change only if expired, like Linux-PAM passwd -k. */
|
2008-06-10 23:20:21 +05:30
|
|
|
kflg = true; /* ok for users */
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'l':
|
2008-06-10 23:20:21 +05:30
|
|
|
lflg = true;
|
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'n':
|
2009-04-11 04:04:23 +05:30
|
|
|
if ( (getlong (optarg, &age_min) == 0)
|
|
|
|
|| (age_min < -1)) {
|
|
|
|
fprintf (stderr,
|
|
|
|
_("%s: invalid numeric argument '%s'\n"),
|
|
|
|
Prog, optarg);
|
|
|
|
usage (E_BAD_ARG);
|
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
nflg = true;
|
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'q':
|
2008-06-10 23:20:21 +05:30
|
|
|
qflg = true; /* ok for users */
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
/* -r repository (files|nis|nisplus) */
|
|
|
|
/* only "files" supported for now */
|
|
|
|
if (strcmp (optarg, "files") != 0) {
|
|
|
|
fprintf (stderr,
|
* lib/groupio.c, lib/groupio.h, lib/pwio.c, lib/pwio.h,
lib/sgroupio.c, lib/sgroupio.h, lib/shadowio.c, lib/shadowio.h:
Added *_dbname() functions to retrieve the name of the databases.
* lib/groupio.c, lib/groupio.h, lib/pwio.c, lib/pwio.h,
lib/sgroupio.c, lib/sgroupio.h, lib/shadowio.c, lib/shadowio.h:
*_name() functions renamed *setname().
* src/grpck.c, src/pwck.c: Likewise.
* lib/groupio.h, lib/pwio.h, lib/sgroupio.h, lib/shadowio.h: Added
the name of the arguments to the prototypes.
* src/chage, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/gpasswd.c, src/groupadd.c, src/groupdel.c,
src/groupmod.c, src/grpck.c, src/grpconv.c, src/grpunconv.c,
src/newusers.c, src/passwd.c, src/pwck.c, src/pwconv.c,
src/pwunconv.c, src/useradd.c, src/userdel.c, src/usermod.c:
Harmonize the erro & syslog messages in case of failure of the
*_lock(), *_open(), *_close(), *_unlock(), *_remove() functions.
* src/chgpasswd.c, src/chpasswd.c, src/usermod.c: Avoid
capitalized messages.
* src/chpasswd.c, src/useradd.c, src/usermod.c: Harmonize messages
in case of inexistent entries.
* src/usermod.c: Harmonize messages in case of already existing
entries.
* src/newusers.c, src/useradd.c: Simplify PAM error handling.
* src/useradd.c: Report failures to unlock files (stderr, syslog,
and audit). But do not fail (continue).
* src/useradd.c (open_files): Do not report to syslog & audit
failures to lock or open the databases. This might be harmless,
and the logs were not already informed that a change was
requested.
* src/usermod.c: It's not the account which is unlocked, but its
password.
2008-08-06 21:27:31 +05:30
|
|
|
_("%s: repository %s not supported\n"),
|
2007-10-07 17:17:01 +05:30
|
|
|
Prog, optarg);
|
|
|
|
exit (E_BAD_ARG);
|
|
|
|
}
|
|
|
|
break;
|
2011-11-07 00:08:16 +05:30
|
|
|
case 'R': /* no-op, handled in process_root_flag () */
|
|
|
|
break;
|
2007-10-07 17:17:01 +05:30
|
|
|
case 'S':
|
2008-06-10 23:20:21 +05:30
|
|
|
Sflg = true; /* ok for users */
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'u':
|
2008-06-10 23:20:21 +05:30
|
|
|
uflg = true;
|
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'w':
|
2009-04-11 04:04:23 +05:30
|
|
|
if ( (getlong (optarg, &warn) == 0)
|
|
|
|
|| (warn < -1)) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: invalid numeric argument '%s'\n"),
|
|
|
|
Prog, optarg);
|
2009-04-11 04:04:23 +05:30
|
|
|
usage (E_BAD_ARG);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2009-04-11 04:04:23 +05:30
|
|
|
wflg = true;
|
2008-06-10 23:20:21 +05:30
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
case 'x':
|
2009-04-11 04:04:23 +05:30
|
|
|
if ( (getlong (optarg, &age_max) == 0)
|
|
|
|
|| (age_max < -1)) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: invalid numeric argument '%s'\n"),
|
|
|
|
Prog, optarg);
|
2009-04-11 04:04:23 +05:30
|
|
|
usage (E_BAD_ARG);
|
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
xflg = true;
|
|
|
|
anyflag = true;
|
2007-10-07 17:17:01 +05:30
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage (E_BAD_ARG);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Now I have to get the user name. The name will be gotten from the
|
|
|
|
* command line if possible. Otherwise it is figured out from the
|
|
|
|
* environment.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
pw = get_my_pwent ();
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == pw) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: Cannot determine your user name.\n"),
|
|
|
|
Prog);
|
2008-08-30 23:57:07 +05:30
|
|
|
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
|
|
|
|
(unsigned long) getuid ()));
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
myname = xstrdup (pw->pw_name);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (optind < argc) {
|
2007-10-07 17:14:02 +05:30
|
|
|
name = argv[optind];
|
2008-06-10 23:20:21 +05:30
|
|
|
} else {
|
2007-10-07 17:14:02 +05:30
|
|
|
name = myname;
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-12-27 03:47:13 +05:30
|
|
|
/*
|
|
|
|
* Make sure that at most one username was specified.
|
|
|
|
*/
|
2008-06-10 23:20:21 +05:30
|
|
|
if (argc > (optind+1)) {
|
2007-12-27 03:47:13 +05:30
|
|
|
usage (E_USAGE);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-12-27 03:47:13 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* The -a flag requires -S, no other flags, no username, and
|
|
|
|
* you must be root. --marekm
|
|
|
|
*/
|
|
|
|
if (aflg) {
|
2008-06-10 23:20:21 +05:30
|
|
|
if (anyflag || !Sflg || (optind < argc)) {
|
2007-10-07 17:14:59 +05:30
|
|
|
usage (E_USAGE);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
if (!amroot) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: Permission denied.\n"),
|
|
|
|
Prog);
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
setpwent ();
|
Ensure that getpwent() is used in setpwent(), getpwent(),
endpwend() sequences (ditto for getgrent(), getspent(), and
getsgent()). The only real (minor) issue was in login, which kept
the passwd file open.
* libmisc/entry.c: Remove unneeded setspent() and endspent() (only
getspnam is called in the middle).
* libmisc/find_new_ids.c: Make sure to close the password and
group files with endpwent() and endgrent().
* libmisc/pwdcheck.c: Remove unneeded endspent() (only getspnam()
is called before).
* src/lastlog.c, src/passwd.c, src/groupmod.c, src/faillog.c,
src/groups.c: Make sure to close
the password file with endpwent().
* src/login.c: Remove unneeded setpwent() (only xgetpwnam is
called before).
* src/login.c, src/newgrp.c: Fix typos in comments.
2008-04-17 03:22:46 +05:30
|
|
|
while ( (pw = getpwent ()) != NULL ) {
|
2007-10-07 17:14:59 +05:30
|
|
|
print_status (pw);
|
Ensure that getpwent() is used in setpwent(), getpwent(),
endpwend() sequences (ditto for getgrent(), getspent(), and
getsgent()). The only real (minor) issue was in login, which kept
the passwd file open.
* libmisc/entry.c: Remove unneeded setspent() and endspent() (only
getspnam is called in the middle).
* libmisc/find_new_ids.c: Make sure to close the password and
group files with endpwent() and endgrent().
* libmisc/pwdcheck.c: Remove unneeded endspent() (only getspnam()
is called before).
* src/lastlog.c, src/passwd.c, src/groupmod.c, src/faillog.c,
src/groups.c: Make sure to close
the password file with endpwent().
* src/login.c: Remove unneeded setpwent() (only xgetpwnam is
called before).
* src/login.c, src/newgrp.c: Fix typos in comments.
2008-04-17 03:22:46 +05:30
|
|
|
}
|
|
|
|
endpwent ();
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_SUCCESS);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* Allow certain users (administrators) to change passwords of
|
2007-10-07 17:14:59 +05:30
|
|
|
* certain users. Not implemented yet. --marekm
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
if (may_change_passwd (myname, name))
|
2007-10-07 17:14:02 +05:30
|
|
|
amroot = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* If any of the flags were given, a user name must be supplied on
|
|
|
|
* the command line. Only an unadorned command line doesn't require
|
|
|
|
* the user's name be given. Also, -x, -n, -w, -i, -e, -d,
|
|
|
|
* -l, -u may appear with each other. -S, -k must appear alone.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* -S now ok for normal users (check status of my own account), and
|
|
|
|
* doesn't require username. --marekm
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2008-06-10 23:20:21 +05:30
|
|
|
if (anyflag && optind >= argc) {
|
2007-10-07 17:14:59 +05:30
|
|
|
usage (E_USAGE);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-10 23:20:21 +05:30
|
|
|
if ( (Sflg && kflg)
|
|
|
|
|| (anyflag && (Sflg || kflg))) {
|
2007-10-07 17:14:59 +05:30
|
|
|
usage (E_USAGE);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (anyflag && !amroot) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr, _("%s: Permission denied.\n"), Prog);
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
* lib/prototypes.h, configure.in, libmisc/Makefile.am,
libmisc/xgetXXbyYY.c, libmisc/xgetpwnam.c, libmisc/xgetpwuid.c,
libmisc/xgetgrnam.c, libmisc/xgetgrgid.c, libmisc/xgetspnam.c:
Added functions xgetpwnam(), xgetpwuid(), xgetgrnam(),
xgetgrgid(), and xgetspnam(). They allocate memory for the
returned structure and are more robust to successive calls. They
are implemented with the libc's getxxyyy_r() functions if
available.
* libmisc/limits.c, libmisc/entry.c, libmisc/chowntty.c,
libmisc/addgrps.c, libmisc/myname.c, libmisc/rlogin.c,
libmisc/pwdcheck.c, src/newgrp.c, src/login_nopam.c,
src/userdel.c, src/lastlog.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/chfn.c, src/groupmems.c,
src/usermod.c, src/expiry.c, src/groupdel.c, src/chgpasswd.c,
src/su.c, src/useradd.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/suauth.c,
src/faillog.c, src/groups.c, src/chsh.c, src/id.c: Review all the
usage of one of the getpwnam(), getpwuid(), getgrnam(),
getgrgid(), and getspnam() functions. It was noticed on
http://bugs.debian.org/341230 that chfn and chsh use a passwd
structure after calling a pam function, which result in using
information from the passwd structure requested by pam, not the
original one. It is much easier to use the new xget... functions
to avoid these issues. I've checked which call to the original
get... functions could be left (reducing the scope of the
structure if possible), and I've left comments to ease future
reviews (e.g. /* local, no need for xgetpwnam */).
Note: the getpwent/getgrent calls should probably be checked also.
* src/groupdel.c, src/expiry.c: Fix typos in comments.
* src/groupmod.c: Re-indent.
* libmisc/Makefile.am, lib/groupmem.c, lib/groupio.c, lib/pwmem.c,
lib/pwio.c, lib/shadowmem.c, lib/shadowio.c: Move the __<xx>_dup
functions (used by the xget... functions) from the <xx>io.c files
to the new <xx>mem.c files. This avoid linking some utils against
the SELinux library.
2007-11-19 04:45:26 +05:30
|
|
|
pw = xgetpwnam (name);
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == pw) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: user '%s' does not exist\n"),
|
|
|
|
Prog, name);
|
2007-10-07 17:14:59 +05:30
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
#ifdef WITH_SELINUX
|
2008-03-27 03:30:50 +05:30
|
|
|
/* only do this check when getuid()==0 because it's a pre-condition for
|
|
|
|
changing a password without entering the old one */
|
2019-10-16 03:03:54 +05:30
|
|
|
if (amroot && (check_selinux_permit ("passwd") != 0)) {
|
2009-04-26 22:14:54 +05:30
|
|
|
SYSLOG ((LOG_ALERT,
|
2019-10-16 03:03:54 +05:30
|
|
|
"root is not authorized by SELinux to change the password of %s",
|
|
|
|
name));
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf(stderr,
|
2019-10-16 03:03:54 +05:30
|
|
|
_("%s: root is not authorized by SELinux to change the password of %s\n"),
|
|
|
|
Prog, name);
|
* src/newgrp.c, src/chfn.c, src/groupmems.c, src/usermod.c,
src/userdel.c, src/chpasswd.c, src/grpck.c, src/gpasswd.c,
src/groupdel.c, src/chgpasswd.c, src/vipw.c, src/useradd.c,
src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/faillog.c,
src/sulogin.c, src/chsh.c, src/pwconv.c: Added splint annotations.
* src/userdel.c, src/pwconv.c, src/lastlog.c, src/grpck.c,
src/vipw.c, src/groupmod.c, src/passwd.c, src/pwck.c, src/login.c,
src/sulogin.c, src/usermod.c: Use return instead of exit at the
end of main().
* src/gpasswd.c, src/passwd.c, src/faillog.c: Use the exitcodes.h
exit codes.
* src/chpasswd.c: Added missing ||.
* src/nologin.c: Do not include exitcodes.h.
* src/nologin.c: Added brackets.
* src/nologin.c: Avoid assignments in comparisons.
2009-05-01 03:09:38 +05:30
|
|
|
exit (E_NOPERM);
|
2008-03-27 03:30:50 +05:30
|
|
|
}
|
2009-04-29 02:25:10 +05:30
|
|
|
#endif /* WITH_SELINUX */
|
2008-03-27 03:30:50 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
/*
|
|
|
|
* If the UID of the user does not match the current real UID,
|
|
|
|
* check if I'm root.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2008-06-10 23:20:21 +05:30
|
|
|
if (!amroot && (pw->pw_uid != getuid ())) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: You may not view or modify password information for %s.\n"),
|
|
|
|
Prog, name);
|
2007-10-07 17:16:07 +05:30
|
|
|
SYSLOG ((LOG_WARN,
|
2010-08-22 18:19:07 +05:30
|
|
|
"%s: can't view or modify password information for %s",
|
|
|
|
Prog, name));
|
2007-10-07 17:14:59 +05:30
|
|
|
closelog ();
|
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
if (Sflg) {
|
2007-10-07 17:14:59 +05:30
|
|
|
print_status (pw);
|
|
|
|
exit (E_SUCCESS);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
#ifndef USE_PAM
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* The user name is valid, so let's get the shadow file entry.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
* lib/prototypes.h, configure.in, libmisc/Makefile.am,
libmisc/xgetXXbyYY.c, libmisc/xgetpwnam.c, libmisc/xgetpwuid.c,
libmisc/xgetgrnam.c, libmisc/xgetgrgid.c, libmisc/xgetspnam.c:
Added functions xgetpwnam(), xgetpwuid(), xgetgrnam(),
xgetgrgid(), and xgetspnam(). They allocate memory for the
returned structure and are more robust to successive calls. They
are implemented with the libc's getxxyyy_r() functions if
available.
* libmisc/limits.c, libmisc/entry.c, libmisc/chowntty.c,
libmisc/addgrps.c, libmisc/myname.c, libmisc/rlogin.c,
libmisc/pwdcheck.c, src/newgrp.c, src/login_nopam.c,
src/userdel.c, src/lastlog.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/chfn.c, src/groupmems.c,
src/usermod.c, src/expiry.c, src/groupdel.c, src/chgpasswd.c,
src/su.c, src/useradd.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/suauth.c,
src/faillog.c, src/groups.c, src/chsh.c, src/id.c: Review all the
usage of one of the getpwnam(), getpwuid(), getgrnam(),
getgrgid(), and getspnam() functions. It was noticed on
http://bugs.debian.org/341230 that chfn and chsh use a passwd
structure after calling a pam function, which result in using
information from the passwd structure requested by pam, not the
original one. It is much easier to use the new xget... functions
to avoid these issues. I've checked which call to the original
get... functions could be left (reducing the scope of the
structure if possible), and I've left comments to ease future
reviews (e.g. /* local, no need for xgetpwnam */).
Note: the getpwent/getgrent calls should probably be checked also.
* src/groupdel.c, src/expiry.c: Fix typos in comments.
* src/groupmod.c: Re-indent.
* libmisc/Makefile.am, lib/groupmem.c, lib/groupio.c, lib/pwmem.c,
lib/pwio.c, lib/shadowmem.c, lib/shadowio.c: Move the __<xx>_dup
functions (used by the xget... functions) from the <xx>io.c files
to the new <xx>mem.c files. This avoid linking some utils against
the SELinux library.
2007-11-19 04:45:26 +05:30
|
|
|
sp = getspnam (name); /* !USE_PAM, no need for xgetspnam */
|
2008-06-10 23:20:21 +05:30
|
|
|
if (NULL == sp) {
|
2012-02-14 02:02:00 +05:30
|
|
|
if (errno == EACCES) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("%s: Permission denied.\n"),
|
|
|
|
Prog);
|
|
|
|
exit (E_NOPERM);
|
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
sp = pwd_to_spwd (pw);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
cp = sp->sp_pwdp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are no other flags, just change the password.
|
|
|
|
*/
|
|
|
|
if (!anyflag) {
|
2007-10-07 17:15:23 +05:30
|
|
|
STRFCPY (crypt_passwd, cp);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
2021-09-13 21:53:17 +05:30
|
|
|
* See if the user is permitted to change the password.
|
2007-10-07 17:14:02 +05:30
|
|
|
* Otherwise, go ahead and set a new password.
|
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
check_password (pw, sp);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* Let the user know whose password is being changed.
|
|
|
|
*/
|
2008-06-10 23:20:21 +05:30
|
|
|
if (!qflg) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) printf (_("Changing password for %s\n"), name);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
|
2010-08-22 18:19:07 +05:30
|
|
|
if (new_password (pw) != 0) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
_("The password for %s is unchanged.\n"),
|
|
|
|
name);
|
2007-10-07 17:14:59 +05:30
|
|
|
closelog ();
|
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
do_update_pwd = true;
|
|
|
|
do_update_age = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
#endif /* !USE_PAM */
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Before going any further, raise the ulimit to prevent colliding
|
|
|
|
* into a lowered ulimit, and set the real UID to root to protect
|
|
|
|
* against unexpected signals. Any keyboard signals are set to be
|
|
|
|
* ignored.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
pwd_init ();
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:17:01 +05:30
|
|
|
#ifdef USE_PAM
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* Don't set the real UID for PAM...
|
|
|
|
*/
|
|
|
|
if (!anyflag) {
|
2007-10-07 17:14:59 +05:30
|
|
|
do_pam_passwd (name, qflg, kflg);
|
|
|
|
exit (E_SUCCESS);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:16:25 +05:30
|
|
|
#endif /* USE_PAM */
|
2008-06-10 23:20:21 +05:30
|
|
|
if (setuid (0) != 0) {
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) fputs (_("Cannot change ID to root.\n"), stderr);
|
2007-10-07 17:14:59 +05:30
|
|
|
SYSLOG ((LOG_ERR, "can't setuid(0)"));
|
|
|
|
closelog ();
|
|
|
|
exit (E_NOPERM);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
if (spw_file_present ()) {
|
2007-10-07 17:14:59 +05:30
|
|
|
update_shadow ();
|
2008-06-10 23:20:21 +05:30
|
|
|
} else {
|
2007-10-07 17:14:59 +05:30
|
|
|
update_noshadow ();
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:15:23 +05:30
|
|
|
nscd_flush_cache ("passwd");
|
|
|
|
nscd_flush_cache ("group");
|
Flush sssd caches in addition to nscd caches
Some distributions, notably Fedora, have the following order of nsswitch
modules by default:
passwd: sss files
group: sss files
The advantage of serving local users through SSSD is that the nss_sss
module has a fast mmapped-cache that speeds up NSS lookups compared to
accessing the disk an opening the files on each NSS request.
Traditionally, this has been done with the help of nscd, but using nscd
in parallel with sssd is cumbersome, as both SSSD and nscd use their own
independent caching, so using nscd in setups where sssd is also serving
users from some remote domain (LDAP, AD, ...) can result in a bit of
unpredictability.
More details about why Fedora chose to use sss before files can be found
on e.g.:
https://fedoraproject.org//wiki/Changes/SSSDCacheForLocalUsers
or:
https://docs.pagure.org/SSSD.sssd/design_pages/files_provider.html
Now, even though sssd watches the passwd and group files with the help
of inotify, there can still be a small window where someone requests a
user or a group, finds that it doesn't exist, adds the entry and checks
again. Without some support in shadow-utils that would explicitly drop
the sssd caches, the inotify watch can fire a little late, so a
combination of commands like this:
getent passwd user || useradd user; getent passwd user
can result in the second getent passwd not finding the newly added user
as the racy behaviour might still return the cached negative hit from
the first getent passwd.
This patch more or less copies the already existing support that
shadow-utils had for dropping nscd caches, except using the "sss_cache"
tool that sssd ships.
2018-09-12 17:52:11 +05:30
|
|
|
sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
|
2007-10-07 17:15:23 +05:30
|
|
|
|
* src/chfn.c, src/chsh.c, src/groupdel.c, src/groupmems.c,
src/groupmod.c, src/grpck.c, src/login.c, src/logoutd.c,
src/newgrp.c, src/newusers.c, src/passwd.c, src/pwck.c,
src/suauth.c, src/useradd.c, src/userdel.c, src/usermod.c,
src/vipw.c: Complete the switch from the `' quotation style to ''.
Do it also in SYSLOG messages. Quote some parameters. All this
permits to merge some messages.
2008-08-06 21:21:52 +05:30
|
|
|
SYSLOG ((LOG_INFO, "password for '%s' changed by '%s'", name, myname));
|
2007-10-07 17:14:59 +05:30
|
|
|
closelog ();
|
2007-10-07 17:17:22 +05:30
|
|
|
if (!qflg) {
|
2009-04-29 02:16:35 +05:30
|
|
|
if (!anyflag) {
|
|
|
|
#ifndef USE_PAM
|
2010-08-22 18:19:07 +05:30
|
|
|
(void) printf (_("%s: password changed.\n"), Prog);
|
2009-04-29 02:16:35 +05:30
|
|
|
#endif /* USE_PAM */
|
2008-06-10 23:20:21 +05:30
|
|
|
} else {
|
2021-12-18 04:29:46 +05:30
|
|
|
(void) printf (_("%s: password changed.\n"), Prog);
|
2008-06-10 23:20:21 +05:30
|
|
|
}
|
2007-10-07 17:17:22 +05:30
|
|
|
}
|
* src/newgrp.c, src/chfn.c, src/groupmems.c, src/usermod.c,
src/userdel.c, src/chpasswd.c, src/grpck.c, src/gpasswd.c,
src/groupdel.c, src/chgpasswd.c, src/vipw.c, src/useradd.c,
src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c,
src/groupadd.c, src/chage.c, src/login.c, src/faillog.c,
src/sulogin.c, src/chsh.c, src/pwconv.c: Added splint annotations.
* src/userdel.c, src/pwconv.c, src/lastlog.c, src/grpck.c,
src/vipw.c, src/groupmod.c, src/passwd.c, src/pwck.c, src/login.c,
src/sulogin.c, src/usermod.c: Use return instead of exit at the
end of main().
* src/gpasswd.c, src/passwd.c, src/faillog.c: Use the exitcodes.h
exit codes.
* src/chpasswd.c: Added missing ||.
* src/nologin.c: Do not include exitcodes.h.
* src/nologin.c: Added brackets.
* src/nologin.c: Avoid assignments in comparisons.
2009-05-01 03:09:38 +05:30
|
|
|
|
|
|
|
return E_SUCCESS;
|
2007-10-07 17:15:23 +05:30
|
|
|
}
|
2008-06-10 23:20:21 +05:30
|
|
|
|