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
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <fcntl.h>
|
2007-10-07 17:17:57 +05:30
|
|
|
#include <getopt.h>
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <pwd.h>
|
2007-10-07 17:16:52 +05:30
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
2023-02-20 01:10:16 +05:30
|
|
|
|
|
|
|
#include "alloc.h"
|
2007-10-07 17:16:52 +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:16:52 +05:30
|
|
|
#include "prototypes.h"
|
|
|
|
#include "pwauth.h"
|
|
|
|
#include "pwio.h"
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef USE_PAM
|
|
|
|
#include "pam_defs.h"
|
|
|
|
#endif
|
* 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@*/
|
|
|
|
#include "exitcodes.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
|
|
|
#ifndef SHELLS_FILE
|
|
|
|
#define SHELLS_FILE "/etc/shells"
|
|
|
|
#endif
|
2022-11-28 21:48:09 +05:30
|
|
|
|
|
|
|
#ifdef HAVE_VENDORDIR
|
|
|
|
#include <libeconf.h>
|
|
|
|
#define SHELLS "shells"
|
|
|
|
#define ETCDIR "/etc"
|
|
|
|
#endif
|
|
|
|
|
2007-10-07 17:17:01 +05:30
|
|
|
/*
|
|
|
|
* 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 */
|
2008-06-11 01:12:22 +05:30
|
|
|
static bool amroot; /* Real UID is root */
|
2007-10-07 17:14:59 +05:30
|
|
|
static char loginsh[BUFSIZ]; /* Name of new login shell */
|
2007-12-31 20:37:59 +05:30
|
|
|
/* command line options */
|
2008-06-11 01:12:22 +05:30
|
|
|
static bool sflg = false; /* -s - set shell from command line */
|
2008-08-10 04:57:50 +05:30
|
|
|
static bool pw_locked = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
/* external identifiers */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/* local function prototypes */
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN static void fail_exit (int code);
|
|
|
|
NORETURN static void usage (int status);
|
2007-10-07 17:14:59 +05:30
|
|
|
static void new_fields (void);
|
2008-06-11 01:12:22 +05:30
|
|
|
static bool shell_is_listed (const char *);
|
|
|
|
static bool is_restricted_shell (const char *);
|
2007-12-31 20:22:52 +05:30
|
|
|
static void process_flags (int argc, char **argv);
|
2007-12-31 20:24:46 +05:30
|
|
|
static void check_perms (const struct passwd *pw);
|
2007-12-31 20:36:22 +05:30
|
|
|
static void update_shell (const char *user, char *loginsh);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-08-10 04:57:50 +05:30
|
|
|
/*
|
|
|
|
* fail_exit - do some cleanup and exit with the given error code
|
|
|
|
*/
|
2023-02-08 00:20:36 +05:30
|
|
|
NORETURN
|
|
|
|
static void
|
|
|
|
fail_exit (int code)
|
2008-08-10 04:57:50 +05:30
|
|
|
{
|
|
|
|
if (pw_locked) {
|
|
|
|
if (pw_unlock () == 0) {
|
|
|
|
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
|
|
|
|
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
|
|
|
|
/* continue */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closelog ();
|
|
|
|
|
|
|
|
exit (code);
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* usage - print command line syntax 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:32 +05:30
|
|
|
FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
|
|
|
|
(void) fprintf (usageout,
|
|
|
|
_("Usage: %s [options] [LOGIN]\n"
|
|
|
|
"\n"
|
|
|
|
"Options:\n"),
|
|
|
|
Prog);
|
|
|
|
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
|
|
|
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
|
|
|
(void) fputs (_(" -s, --shell SHELL new login shell for the user account\n"), usageout);
|
|
|
|
(void) fputs ("\n", usageout);
|
* NEWS, src/userdel.c, src/lastlog.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/groupmems.c, src/usermod.c,
src/chgpasswd.c, src/vipw.c, src/su.c, src/useradd.c,
src/groupmod.c, src/passwd.c, src/groupadd.c, src/chage.c,
src/faillog.c, src/chsh.c: If someone uses the -h/--help options,
the usage should not go to stderr nor should the utility exit with
non-zero status. All of the shadow utils do just this
unfortunately, so convert them over to sanity.
* man/groupmems.8.xml, man/gpasswd.1.xml: Added option -h/--help.
2009-09-05 04:32:33 +05:30
|
|
|
exit (status);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* new_fields - change the user's login shell information interactively
|
|
|
|
*
|
|
|
|
* prompt the user for the login shell and change it according to the
|
|
|
|
* response, or leave it alone if nothing was entered.
|
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
static void new_fields (void)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
* libmisc/age.c, libmisc/yesno.c, src/lastlog.c, src/grpck.c,
src/chfn.c, src/passwd.c, src/chage.c, src/login.c, src/sulogin.c,
src/chsh.c: Fix call to puts (remove end of line, or use fputs).
* po/*.po: Unfuzzy PO files according to above change.
2008-02-03 21:58:03 +05:30
|
|
|
puts (_("Enter the new value, or press ENTER for the default"));
|
2007-10-07 17:14:59 +05:30
|
|
|
change_field (loginsh, sizeof loginsh, _("Login Shell"));
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-06-11 01:12:22 +05:30
|
|
|
* is_restricted_shell - return true if the shell is restricted
|
2007-10-07 17:14:02 +05:30
|
|
|
*
|
|
|
|
*/
|
2008-06-11 01:12:22 +05:30
|
|
|
static bool is_restricted_shell (const char *sh)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Shells not listed in /etc/shells are considered to be restricted.
|
|
|
|
* Changed this to avoid confusion with "rc" (the plan9 shell - not
|
|
|
|
* restricted despite the name starting with 'r'). --marekm
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2008-06-11 01:12:22 +05:30
|
|
|
return !shell_is_listed (sh);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:17:11 +05:30
|
|
|
/*
|
2008-06-11 01:12:22 +05:30
|
|
|
* shell_is_listed - see if the user's login shell is listed in /etc/shells
|
2007-10-07 17:17:11 +05:30
|
|
|
*
|
|
|
|
* The /etc/shells file is read for valid names of login shells. If the
|
|
|
|
* /etc/shells file does not exist the user cannot set any shell unless
|
|
|
|
* they are root.
|
|
|
|
*
|
|
|
|
* If getusershell() is available (Linux, *BSD, possibly others), use it
|
|
|
|
* instead of re-implementing it.
|
|
|
|
*/
|
2022-11-28 21:48:09 +05:30
|
|
|
|
|
|
|
#ifdef HAVE_VENDORDIR
|
2008-06-11 01:12:22 +05:30
|
|
|
static bool shell_is_listed (const char *sh)
|
2007-10-07 17:17:11 +05:30
|
|
|
{
|
2008-06-11 01:12:22 +05:30
|
|
|
bool found = false;
|
2007-10-07 17:17:11 +05:30
|
|
|
|
2022-11-28 21:48:09 +05:30
|
|
|
size_t size = 0;
|
|
|
|
econf_err error;
|
|
|
|
char **keys;
|
|
|
|
econf_file *key_file;
|
|
|
|
|
|
|
|
error = econf_readDirs(&key_file,
|
|
|
|
VENDORDIR,
|
|
|
|
ETCDIR,
|
|
|
|
SHELLS,
|
|
|
|
NULL,
|
|
|
|
"", /* key only */
|
|
|
|
"#" /* comment */);
|
|
|
|
if (error) {
|
|
|
|
fprintf (stderr,
|
|
|
|
_("Cannot parse shell files: %s"),
|
|
|
|
econf_errString(error));
|
|
|
|
fail_exit (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
error = econf_getKeys(key_file, NULL, &size, &keys);
|
|
|
|
if (error) {
|
|
|
|
fprintf (stderr,
|
|
|
|
_("Cannot evaluate entries in shell files: %s"),
|
|
|
|
econf_errString(error));
|
|
|
|
econf_free (key_file);
|
|
|
|
fail_exit (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; i++) {
|
|
|
|
if (strcmp (keys[i], sh) == 0) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
econf_free (key_file);
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* without HAVE_VENDORDIR */
|
|
|
|
|
|
|
|
static bool shell_is_listed (const char *sh)
|
|
|
|
{
|
|
|
|
bool found = false;
|
2007-10-07 17:17:11 +05:30
|
|
|
|
|
|
|
#ifdef HAVE_GETUSERSHELL
|
2022-11-28 21:48:09 +05:30
|
|
|
char *cp;
|
2007-10-07 17:17:11 +05:30
|
|
|
setusershell ();
|
|
|
|
while ((cp = getusershell ())) {
|
|
|
|
if (strcmp (cp, sh) == 0) {
|
2008-06-11 01:12:22 +05:30
|
|
|
found = true;
|
2007-10-07 17:17:11 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endusershell ();
|
|
|
|
#else
|
2022-11-28 21:48:09 +05:30
|
|
|
char buf[BUFSIZ];
|
|
|
|
FILE *fp;
|
|
|
|
|
2007-12-31 21:00:29 +05:30
|
|
|
fp = fopen (SHELLS_FILE, "r");
|
|
|
|
if (NULL == fp) {
|
2008-06-11 01:12:22 +05:30
|
|
|
return false;
|
2007-12-31 21:00:29 +05:30
|
|
|
}
|
2007-10-07 17:17:11 +05:30
|
|
|
|
2008-06-11 03:40:47 +05:30
|
|
|
while (fgets (buf, sizeof (buf), fp) == buf) {
|
2007-12-31 21:00:29 +05:30
|
|
|
cp = strrchr (buf, '\n');
|
|
|
|
if (NULL != cp) {
|
2007-10-07 17:17:11 +05:30
|
|
|
*cp = '\0';
|
2007-12-31 20:57:23 +05:30
|
|
|
}
|
2007-10-07 17:17:11 +05:30
|
|
|
|
2007-12-31 20:57:23 +05:30
|
|
|
if (buf[0] == '#') {
|
2007-10-07 17:17:11 +05:30
|
|
|
continue;
|
2007-12-31 20:57:23 +05:30
|
|
|
}
|
2007-10-07 17:17:11 +05:30
|
|
|
|
|
|
|
if (strcmp (buf, sh) == 0) {
|
2008-06-11 01:12:22 +05:30
|
|
|
found = true;
|
2007-10-07 17:17:11 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose (fp);
|
|
|
|
#endif
|
|
|
|
return found;
|
|
|
|
}
|
2022-11-28 21:48:09 +05:30
|
|
|
#endif /* with HAVE_VENDORDIR */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-12-31 20:22:52 +05:30
|
|
|
/*
|
2011-11-07 00:09:42 +05:30
|
|
|
* process_flags - parse the command line options
|
2007-12-31 20:22:52 +05:30
|
|
|
*
|
|
|
|
* It will not return if an error is encountered.
|
|
|
|
*/
|
|
|
|
static void process_flags (int argc, char **argv)
|
|
|
|
{
|
|
|
|
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
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
{"root", required_argument, NULL, 'R'},
|
2007-12-31 20:22:52 +05:30
|
|
|
{"shell", required_argument, NULL, 's'},
|
|
|
|
{NULL, 0, NULL, '\0'}
|
|
|
|
};
|
|
|
|
|
2011-11-07 00:08:32 +05:30
|
|
|
while ((c = getopt_long (argc, argv, "hR:s:",
|
|
|
|
long_options, NULL)) != -1) {
|
2007-12-31 20:22:52 +05:30
|
|
|
switch (c) {
|
|
|
|
case 'h':
|
* NEWS, src/userdel.c, src/lastlog.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/groupmems.c, src/usermod.c,
src/chgpasswd.c, src/vipw.c, src/su.c, src/useradd.c,
src/groupmod.c, src/passwd.c, src/groupadd.c, src/chage.c,
src/faillog.c, src/chsh.c: If someone uses the -h/--help options,
the usage should not go to stderr nor should the utility exit with
non-zero status. All of the shadow utils do just this
unfortunately, so convert them over to sanity.
* man/groupmems.8.xml, man/gpasswd.1.xml: Added option -h/--help.
2009-09-05 04:32:33 +05:30
|
|
|
usage (E_SUCCESS);
|
2011-11-20 03:21:52 +05:30
|
|
|
/*@notreached@*/break;
|
2011-11-07 00:08:32 +05:30
|
|
|
case 'R': /* no-op, handled in process_root_flag () */
|
|
|
|
break;
|
2007-12-31 20:22:52 +05:30
|
|
|
case 's':
|
2008-06-11 01:12:22 +05:30
|
|
|
sflg = true;
|
2007-12-31 20:22:52 +05:30
|
|
|
STRFCPY (loginsh, optarg);
|
|
|
|
break;
|
|
|
|
default:
|
* NEWS, src/userdel.c, src/lastlog.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/groupmems.c, src/usermod.c,
src/chgpasswd.c, src/vipw.c, src/su.c, src/useradd.c,
src/groupmod.c, src/passwd.c, src/groupadd.c, src/chage.c,
src/faillog.c, src/chsh.c: If someone uses the -h/--help options,
the usage should not go to stderr nor should the utility exit with
non-zero status. All of the shadow utils do just this
unfortunately, so convert them over to sanity.
* man/groupmems.8.xml, man/gpasswd.1.xml: Added option -h/--help.
2009-09-05 04:32:33 +05:30
|
|
|
usage (E_USAGE);
|
2007-12-31 20:22:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There should be only one remaining argument at most and it should
|
|
|
|
* be the user's name.
|
|
|
|
*/
|
|
|
|
if (argc > (optind + 1)) {
|
* NEWS, src/userdel.c, src/lastlog.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/groupmems.c, src/usermod.c,
src/chgpasswd.c, src/vipw.c, src/su.c, src/useradd.c,
src/groupmod.c, src/passwd.c, src/groupadd.c, src/chage.c,
src/faillog.c, src/chsh.c: If someone uses the -h/--help options,
the usage should not go to stderr nor should the utility exit with
non-zero status. All of the shadow utils do just this
unfortunately, so convert them over to sanity.
* man/groupmems.8.xml, man/gpasswd.1.xml: Added option -h/--help.
2009-09-05 04:32:33 +05:30
|
|
|
usage (E_USAGE);
|
2007-12-31 20:22:52 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-31 20:24:46 +05:30
|
|
|
/*
|
|
|
|
* check_perms - check if the caller is allowed to add a group
|
|
|
|
*
|
|
|
|
* Non-root users are only allowed to change their shell, if their current
|
|
|
|
* shell is not a restricted shell.
|
|
|
|
*
|
|
|
|
* Non-root users must be authenticated.
|
|
|
|
*
|
|
|
|
* It will not return if the user is not allowed.
|
|
|
|
*/
|
|
|
|
static void check_perms (const struct passwd *pw)
|
|
|
|
{
|
|
|
|
#ifdef USE_PAM
|
* src/userdel.c, src/newusers.c, src/chpasswd.c, src/chfn.c,
src/groupmems.c, src/usermod.c, src/groupdel.c, src/chgpasswd.c,
src/useradd.c, src/groupmod.c, src/groupadd.c, src/chage.c,
src/chsh.c: Simplify the PAM error handling. Do not keep the pamh
handle, but terminate the PAM transaction as soon as possible if
there are no PAM session opened.
2008-09-06 18:58:02 +05:30
|
|
|
pam_handle_t *pamh = NULL;
|
2007-12-31 20:24:46 +05:30
|
|
|
int retval;
|
|
|
|
struct passwd *pampw;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Non-privileged users are only allowed to change the shell if the
|
|
|
|
* UID of the user matches the current real UID.
|
|
|
|
*/
|
|
|
|
if (!amroot && pw->pw_uid != getuid ()) {
|
* 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, "can't change shell for '%s'", pw->pw_name));
|
2007-12-31 20:24:46 +05:30
|
|
|
fprintf (stderr,
|
* 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
|
|
|
_("You may not change the shell for '%s'.\n"),
|
2007-12-31 20:43:39 +05:30
|
|
|
pw->pw_name);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:24:46 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Non-privileged users are only allowed to change the shell if it
|
|
|
|
* is not a restricted one.
|
|
|
|
*/
|
2008-06-11 01:12:22 +05:30
|
|
|
if (!amroot && is_restricted_shell (pw->pw_shell)) {
|
* 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, "can't change shell for '%s'", pw->pw_name));
|
2007-12-31 20:24:46 +05:30
|
|
|
fprintf (stderr,
|
* 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
|
|
|
_("You may not change the shell for '%s'.\n"),
|
2007-12-31 20:43:39 +05:30
|
|
|
pw->pw_name);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:24:46 +05:30
|
|
|
}
|
|
|
|
#ifdef WITH_SELINUX
|
|
|
|
/*
|
|
|
|
* If the UID of the user does not match the current real UID,
|
|
|
|
* check if the change is allowed by SELinux policy.
|
|
|
|
*/
|
|
|
|
if ((pw->pw_uid != getuid ())
|
2019-10-16 03:03:54 +05:30
|
|
|
&& (check_selinux_permit("chsh") != 0)) {
|
* 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, "can't change shell for '%s'", pw->pw_name));
|
2007-12-31 20:24:46 +05:30
|
|
|
fprintf (stderr,
|
* 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
|
|
|
_("You may not change the shell for '%s'.\n"),
|
2007-12-31 20:43:39 +05:30
|
|
|
pw->pw_name);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:24:46 +05:30
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef USE_PAM
|
|
|
|
/*
|
|
|
|
* Non-privileged users are optionally authenticated (must enter
|
|
|
|
* the password of the user whose information is being changed)
|
|
|
|
* before any changes can be made. Idea from util-linux
|
|
|
|
* chfn/chsh. --marekm
|
|
|
|
*/
|
|
|
|
if (!amroot && getdef_bool ("CHSH_AUTH")) {
|
|
|
|
passwd_check (pw->pw_name, pw->pw_passwd, "chsh");
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !USE_PAM */
|
|
|
|
pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
|
2008-08-10 04:57:50 +05:30
|
|
|
if (NULL == pampw) {
|
Additional PAM cleanup:
* src/userdel.c, src/newusers.c, src/chpasswd.c, src/chfn.c,
src/groupmems.c, src/usermod.c, src/groupdel.c, src/chgpasswd.c,
src/useradd.c, src/groupmod.c, src/groupadd.c, src/chage.c,
src/chsh.c: If the username cannot be determined, report it as
such (not a PAM authentication failure).
2008-09-07 05:16:44 +05:30
|
|
|
fprintf (stderr,
|
|
|
|
_("%s: Cannot determine your user name.\n"),
|
|
|
|
Prog);
|
|
|
|
exit (E_NOPERM);
|
2007-12-31 20:24:46 +05:30
|
|
|
}
|
|
|
|
|
Additional PAM cleanup:
* src/userdel.c, src/newusers.c, src/chpasswd.c, src/chfn.c,
src/groupmems.c, src/usermod.c, src/groupdel.c, src/chgpasswd.c,
src/useradd.c, src/groupmod.c, src/groupadd.c, src/chage.c,
src/chsh.c: If the username cannot be determined, report it as
such (not a PAM authentication failure).
2008-09-07 05:16:44 +05:30
|
|
|
retval = pam_start ("chsh", pampw->pw_name, &conv, &pamh);
|
|
|
|
|
2008-08-10 04:57:50 +05:30
|
|
|
if (PAM_SUCCESS == retval) {
|
2007-12-31 20:24:46 +05:30
|
|
|
retval = pam_authenticate (pamh, 0);
|
|
|
|
}
|
|
|
|
|
2008-08-10 04:57:50 +05:30
|
|
|
if (PAM_SUCCESS == retval) {
|
2007-12-31 20:24:46 +05:30
|
|
|
retval = pam_acct_mgmt (pamh, 0);
|
|
|
|
}
|
|
|
|
|
* src/userdel.c, src/newusers.c, src/chpasswd.c, src/chfn.c,
src/groupmems.c, src/usermod.c, src/groupdel.c, src/chgpasswd.c,
src/useradd.c, src/groupmod.c, src/groupadd.c, src/chage.c,
src/chsh.c: Simplify the PAM error handling. Do not keep the pamh
handle, but terminate the PAM transaction as soon as possible if
there are no PAM session opened.
2008-09-06 18:58:02 +05:30
|
|
|
if (PAM_SUCCESS != retval) {
|
* src/chage.c, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/groupadd.c, src/groupdel.c, src/groupmems.c,
src/groupmod.c, src/newusers.c, src/useradd.c, src/userdel.c,
src/usermod.c: Provide the PAM error
message instead of our own, and log error to syslog.
* src/groupmems.c: Exit with exit rather than fail_exit in usage().
* src/newusers.c: Check the number of arguments.
* src/newusers.c: Do not create the home directory when it is not
changed.
* src/useradd.c: Set the group password to "!" rather "x" if there
are no gshadow file.
2011-11-13 21:54:57 +05:30
|
|
|
fprintf (stderr, _("%s: PAM: %s\n"),
|
|
|
|
Prog, pam_strerror (pamh, retval));
|
|
|
|
SYSLOG((LOG_ERR, "%s", pam_strerror (pamh, retval)));
|
|
|
|
if (NULL != pamh) {
|
|
|
|
(void) pam_end (pamh, retval);
|
|
|
|
}
|
2007-12-31 20:24:46 +05:30
|
|
|
exit (E_NOPERM);
|
|
|
|
}
|
* src/chage.c, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/groupadd.c, src/groupdel.c, src/groupmems.c,
src/groupmod.c, src/newusers.c, src/useradd.c, src/userdel.c,
src/usermod.c: Provide the PAM error
message instead of our own, and log error to syslog.
* src/groupmems.c: Exit with exit rather than fail_exit in usage().
* src/newusers.c: Check the number of arguments.
* src/newusers.c: Do not create the home directory when it is not
changed.
* src/useradd.c: Set the group password to "!" rather "x" if there
are no gshadow file.
2011-11-13 21:54:57 +05:30
|
|
|
(void) pam_end (pamh, retval);
|
2007-12-31 20:24:46 +05:30
|
|
|
#endif /* USE_PAM */
|
|
|
|
}
|
|
|
|
|
2007-12-31 20:36:22 +05:30
|
|
|
/*
|
|
|
|
* update_shell - update the user's shell in the passwd database
|
|
|
|
*
|
|
|
|
* Commit the user's entry after changing her shell field.
|
|
|
|
*
|
|
|
|
* It will not return in case of error.
|
|
|
|
*/
|
2008-01-05 19:24:39 +05:30
|
|
|
static void update_shell (const char *user, char *newshell)
|
2007-12-31 20:36:22 +05:30
|
|
|
{
|
|
|
|
const struct passwd *pw; /* Password entry from /etc/passwd */
|
|
|
|
struct passwd pwent; /* New password entry */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
if (setuid (0) != 0) {
|
|
|
|
SYSLOG ((LOG_ERR, "can't setuid(0)"));
|
2008-01-25 00:09:05 +05:30
|
|
|
fputs (_("Cannot change ID to root.\n"), stderr);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
|
|
|
pwd_init ();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The passwd entry is now ready to be committed back to
|
|
|
|
* the password file. Get a lock on the file and open it.
|
|
|
|
*/
|
|
|
|
if (pw_lock () == 0) {
|
* 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
|
|
|
fprintf (stderr, _("%s: cannot lock %s; try again later.\n"),
|
|
|
|
Prog, pw_dbname ());
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
2008-08-10 04:57:50 +05:30
|
|
|
pw_locked = true;
|
2015-02-27 18:47:25 +05:30
|
|
|
if (pw_open (O_CREAT | O_RDWR) == 0) {
|
* 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
|
|
|
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 ()));
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the entry to update using pw_locate() - we want the real
|
|
|
|
* one from /etc/passwd, not the one from getpwnam() which could
|
|
|
|
* contain the shadow password if (despite the warnings) someone
|
|
|
|
* enables AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm
|
|
|
|
*/
|
|
|
|
pw = pw_locate (user);
|
|
|
|
if (NULL == pw) {
|
|
|
|
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: user '%s' does not exist in %s\n"),
|
|
|
|
Prog, user, pw_dbname ());
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a copy of the entry, then change the shell field. The other
|
|
|
|
* fields remain unchanged.
|
|
|
|
*/
|
|
|
|
pwent = *pw;
|
2008-01-05 19:24:39 +05:30
|
|
|
pwent.pw_shell = newshell;
|
2007-12-31 20:36:22 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the passwd file entry. If there is a DBM file, update
|
|
|
|
* that entry as well.
|
|
|
|
*/
|
|
|
|
if (pw_update (&pwent) == 0) {
|
* src/groupmems.c: Check the return value of gr_update().
* src/chage.c, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/gpasswd.c, src/groupadd.c, src/groupmems.c,
src/groupmod.c, src/grpck.c, src/grpconv.c, src/grpunconv.c,
src/passwd.c, src/pwck.c, src/pwconv.c, src/pwunconv.c,
src/useradd.c, src/userdel.c, src/usermod.c: Harmonize the error
message sent to stderr in case of *_update () failure.
* src/chage.c, src/chsh.c, src/groupadd.c, src/passwd.c: Do not
log to syslog when pw_update() or spw_update() fail.
* src/newusers.c: Do not log specific error message to stderr when
sgr_update() fails.
* src/pwconv.c: Remove duplicated definition of Prog.
2008-08-30 23:57:34 +05:30
|
|
|
fprintf (stderr,
|
2008-08-30 23:58:24 +05:30
|
|
|
_("%s: failed to prepare the new %s entry '%s'\n"),
|
|
|
|
Prog, pw_dbname (), pwent.pw_name);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Changes have all been made, so commit them and unlock the file.
|
|
|
|
*/
|
|
|
|
if (pw_close () == 0) {
|
* 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
|
|
|
fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
|
2008-08-10 04:57:50 +05:30
|
|
|
SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
|
|
|
|
fail_exit (1);
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
|
|
|
if (pw_unlock () == 0) {
|
2008-08-10 04:57:50 +05:30
|
|
|
fprintf (stderr, _("%s: failed to unlock %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, "failed to unlock %s", pw_dbname ()));
|
2008-08-10 04:57:50 +05:30
|
|
|
/* continue */
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
2008-08-10 04:57:50 +05:30
|
|
|
pw_locked= false;
|
2007-12-31 20:36:22 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* chsh - this command controls changes to the user's shell
|
|
|
|
*
|
2007-10-07 17:14:59 +05:30
|
|
|
* The only supported option is -s which permits the the login shell to
|
|
|
|
* be set from the command line.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
int main (int argc, char **argv)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:14:59 +05:30
|
|
|
char *user; /* User name */
|
2007-10-07 17:14:02 +05:30
|
|
|
const struct passwd *pw; /* Password entry from /etc/passwd */
|
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
sanitize_env ();
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2011-11-07 00:08:32 +05:30
|
|
|
/*
|
|
|
|
* 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:32 +05:30
|
|
|
|
2008-06-11 01:12:22 +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:32 +05:30
|
|
|
process_root_flag ("-R", argc, argv);
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* This command behaves different for root and non-root users.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2008-06-11 01:12:22 +05:30
|
|
|
amroot = (getuid () == 0);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
OPENLOG ("chsh");
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-12-31 20:22:52 +05:30
|
|
|
/* parse the command line options */
|
|
|
|
process_flags (argc, argv);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Get the name of the user to check. It is either the command line
|
|
|
|
* name, or the name getlogin() returns.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
if (optind < argc) {
|
|
|
|
user = argv[optind];
|
* 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 (user);
|
2008-06-11 01:12:22 +05:30
|
|
|
if (NULL == pw) {
|
2007-10-07 17:14:59 +05:30
|
|
|
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: user '%s' does not exist\n"), Prog, user);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
} else {
|
2007-10-07 17:14:59 +05:30
|
|
|
pw = get_my_pwent ();
|
2008-06-11 01:12:22 +05:30
|
|
|
if (NULL == pw) {
|
2007-10-07 17:14:59 +05:30
|
|
|
fprintf (stderr,
|
2008-08-10 04:57:50 +05:30
|
|
|
_("%s: Cannot determine your user name.\n"),
|
2007-12-31 21:02:15 +05:30
|
|
|
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 ()));
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:14:59 +05:30
|
|
|
user = xstrdup (pw->pw_name);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_NIS
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Now we make sure this is a LOCAL password entry for this user ...
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
if (__ispwNIS ()) {
|
2007-10-07 17:14:59 +05:30
|
|
|
char *nis_domain;
|
|
|
|
char *nis_master;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
fprintf (stderr,
|
2007-12-31 21:02:15 +05:30
|
|
|
_("%s: cannot change user '%s' on NIS client.\n"),
|
|
|
|
Prog, user);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
if (!yp_get_default_domain (&nis_domain) &&
|
2007-10-07 17:16:07 +05:30
|
|
|
!yp_master (nis_domain, "passwd.byname", &nis_master)) {
|
2007-10-07 17:14:59 +05:30
|
|
|
fprintf (stderr,
|
2008-08-10 04:57:50 +05:30
|
|
|
_("%s: '%s' is the NIS master for this client.\n"),
|
2007-12-31 21:02:15 +05:30
|
|
|
Prog, nis_master);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-12-31 20:24:46 +05:30
|
|
|
check_perms (pw);
|
2007-10-07 17:16:07 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Now get the login shell. Either get it from the password
|
2007-10-07 17:14:02 +05:30
|
|
|
* file, or use the value from the command line.
|
|
|
|
*/
|
2007-12-31 20:57:23 +05:30
|
|
|
if (!sflg) {
|
2007-10-07 17:14:59 +05:30
|
|
|
STRFCPY (loginsh, pw->pw_shell);
|
2007-12-31 20:57:23 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* If the login shell was not set on the command line, let the user
|
|
|
|
* interactively change it.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
2007-10-07 17:14:59 +05:30
|
|
|
if (!sflg) {
|
|
|
|
printf (_("Changing the login shell for %s\n"), user);
|
|
|
|
new_fields ();
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-10-07 17:14:59 +05:30
|
|
|
* Check all of the fields for valid information. The shell
|
|
|
|
* field may not contain any illegal characters. Non-privileged
|
2007-10-07 17:14:02 +05:30
|
|
|
* users are restricted to using the shells in /etc/shells.
|
|
|
|
* The shell must be executable by the user.
|
|
|
|
*/
|
2011-02-16 05:48:45 +05:30
|
|
|
if (valid_field (loginsh, ":,=\n") != 0) {
|
2007-10-07 17:16:07 +05:30
|
|
|
fprintf (stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2008-06-11 01:12:22 +05:30
|
|
|
if ( !amroot
|
|
|
|
&& ( is_restricted_shell (loginsh)
|
|
|
|
|| (access (loginsh, X_OK) != 0))) {
|
2010-03-19 04:51:00 +05:30
|
|
|
fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh);
|
2008-08-10 04:57:50 +05:30
|
|
|
fail_exit (1);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2010-03-19 04:51:00 +05:30
|
|
|
/* Even for root, warn if an invalid shell is specified. */
|
|
|
|
if (access (loginsh, F_OK) != 0) {
|
|
|
|
fprintf (stderr, _("%s: Warning: %s does not exist\n"), Prog, loginsh);
|
|
|
|
} else if (access (loginsh, X_OK) != 0) {
|
|
|
|
fprintf (stderr, _("%s: Warning: %s is not executable\n"), Prog, loginsh);
|
|
|
|
}
|
|
|
|
|
2007-12-31 20:36:22 +05:30
|
|
|
update_shell (user, loginsh);
|
2007-10-07 17:14:02 +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, "changed user '%s' shell to '%s'", user, loginsh));
|
2007-10-07 17:15:23 +05:30
|
|
|
|
|
|
|
nscd_flush_cache ("passwd");
|
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);
|
2007-10-07 17:15:23 +05:30
|
|
|
|
2007-10-07 17:14:59 +05:30
|
|
|
closelog ();
|
2007-10-07 17:16:52 +05:30
|
|
|
exit (E_SUCCESS);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-12-31 20:57:23 +05:30
|
|
|
|